From nobody at rubyforge.org Fri May 23 04:49:28 2008 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 23 May 2008 04:49:28 -0400 (EDT) Subject: [Muby-submits] [266] trunk/lib: made HelperMethods include Styled, to facilitat actually DOING the example "/print RED, 'my red text'" Message-ID: <20080523084930.7B00518585CC@rubyforge.org> Revision: 266 Author: zond Date: 2008-05-23 04:49:17 -0400 (Fri, 23 May 2008) Log Message: ----------- made HelperMethods include Styled, to facilitat actually DOING the example "/print RED, 'my red text'" Modified Paths: -------------- trunk/lib/muby/configuration.rb trunk/lib/muby/helper_methods.rb trunk/lib/muby.rb Modified: trunk/lib/muby/configuration.rb =================================================================== --- trunk/lib/muby/configuration.rb 2008-02-27 10:52:44 UTC (rev 265) +++ trunk/lib/muby/configuration.rb 2008-05-23 08:49:17 UTC (rev 266) @@ -4,7 +4,7 @@ module Muby - VERSION = "0.7.6" unless defined?(Muby::VERSION) + VERSION = "0.7.7" unless defined?(Muby::VERSION) # # The class that encapsulates all configuration. Modified: trunk/lib/muby/helper_methods.rb =================================================================== --- trunk/lib/muby/helper_methods.rb 2008-02-27 10:52:44 UTC (rev 265) +++ trunk/lib/muby/helper_methods.rb 2008-05-23 08:49:17 UTC (rev 266) @@ -3,6 +3,8 @@ module HelperMethods + include Muby::Styled + def execute(command, *args) execute_with_verbosity(:debug, command, *args) end Modified: trunk/lib/muby.rb =================================================================== --- trunk/lib/muby.rb 2008-02-27 10:52:44 UTC (rev 265) +++ trunk/lib/muby.rb 2008-05-23 08:49:17 UTC (rev 266) @@ -1,12 +1,12 @@ $: << File.join(File.dirname(__FILE__), "lib") require 'pp' -require "muby/helper_methods" require "muby/user_window" -require "muby/user_methods" require "muby/displayer" require "muby/configuration" require "muby/logger" require "muby/style" +require "muby/helper_methods" +require "muby/user_methods" require "muby/outputwindow" require "muby/inputwindow" require "muby/connection" From nobody at rubyforge.org Fri May 23 04:52:15 2008 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 23 May 2008 04:52:15 -0400 (EDT) Subject: [Muby-submits] [267] tags/release_0_7_7/: made release 0.7.7 Message-ID: <20080523085215.77F5D18585CD@rubyforge.org> Revision: 267 Author: zond Date: 2008-05-23 04:52:14 -0400 (Fri, 23 May 2008) Log Message: ----------- made release 0.7.7 Added Paths: ----------- tags/release_0_7_7/ Copied: tags/release_0_7_7 (from rev 266, trunk) From nobody at rubyforge.org Fri May 23 20:44:39 2008 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 23 May 2008 20:44:39 -0400 (EDT) Subject: [Muby-submits] [268] trunk/lib/muby: made the TELNET_COMMANDS hash not redefine itself if already defined Message-ID: <20080524004439.54A4D18585D6@rubyforge.org> Revision: 268 Author: zond Date: 2008-05-23 20:44:38 -0400 (Fri, 23 May 2008) Log Message: ----------- made the TELNET_COMMANDS hash not redefine itself if already defined Modified Paths: -------------- trunk/lib/muby/configuration.rb trunk/lib/muby/connection.rb Modified: trunk/lib/muby/configuration.rb =================================================================== --- trunk/lib/muby/configuration.rb 2008-05-23 08:52:14 UTC (rev 267) +++ trunk/lib/muby/configuration.rb 2008-05-24 00:44:38 UTC (rev 268) @@ -4,7 +4,7 @@ module Muby - VERSION = "0.7.7" unless defined?(Muby::VERSION) + VERSION = "0.7.8" unless defined?(Muby::VERSION) # # The class that encapsulates all configuration. Modified: trunk/lib/muby/connection.rb =================================================================== --- trunk/lib/muby/connection.rb 2008-05-23 08:52:14 UTC (rev 267) +++ trunk/lib/muby/connection.rb 2008-05-24 00:44:38 UTC (rev 268) @@ -150,19 +150,21 @@ c end - TELNET_COMMANDS = { - 240 => :end_of_sub_negotiation, - 241 => :noop, - 242 => :data_mark, - 243 => :break, - 249 => :go_ahead, - 250 => :sub_negotiation, - 251 => :will, - 252 => :wont, - 253 => :do, - 254 => :dont, - 255 => :iac - } + unless defined?(TELNET_COMMANDS) + TELNET_COMMANDS = { + 240 => :end_of_sub_negotiation, + 241 => :noop, + 242 => :data_mark, + 243 => :break, + 249 => :go_ahead, + 250 => :sub_negotiation, + 251 => :will, + 252 => :wont, + 253 => :do, + 254 => :dont, + 255 => :iac + } + end # # This is not telnet command OR ansi, lets treat it as nice MUD text! From nobody at rubyforge.org Fri May 23 20:45:05 2008 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 23 May 2008 20:45:05 -0400 (EDT) Subject: [Muby-submits] [269] tags: made release 0.7.8 Message-ID: <20080524004505.4102918585D6@rubyforge.org> Revision: 269 Author: zond Date: 2008-05-23 20:45:04 -0400 (Fri, 23 May 2008) Log Message: ----------- made release 0.7.8 Added Paths: ----------- tags/release_0_7_8/ tags/release_0_7_8/lib/muby/configuration.rb tags/release_0_7_8/lib/muby/connection.rb Removed Paths: ------------- tags/release_0_7_8/lib/muby/configuration.rb tags/release_0_7_8/lib/muby/connection.rb Copied: tags/release_0_7_8 (from rev 267, trunk) Deleted: tags/release_0_7_8/lib/muby/configuration.rb =================================================================== --- trunk/lib/muby/configuration.rb 2008-05-23 08:52:14 UTC (rev 267) +++ tags/release_0_7_8/lib/muby/configuration.rb 2008-05-24 00:45:04 UTC (rev 269) @@ -1,389 +0,0 @@ - -require 'ncurses' - -module Muby - - - VERSION = "0.7.7" unless defined?(Muby::VERSION) - - # - # The class that encapsulates all configuration. - # - # To simplify its use, include Muby::Configurable in your class. - # Then you can access Configuration as 'conf' (nice shorthand :) - # - # All options in Configuration are get'able and set'able. - # - # Look in help.rb to get the meaning of them. - # - class Configuration - - @@instance ||= nil - - def self.get - @@instance ||= Configuration.new - end - - def initialize - # - # verbosity options - # - - @extra_verbosity_settings = { - :echo_keycodes => true, - :echo => true, - :show_level => :debug, - :timestamp => true, - :connection_status => true - } - - @output_window_geometry = { - :top => 0, - :left => 0, - :width => "Ncurses.COLS", - :height => "Ncurses.LINES - Muby::InputWindow.get_instance.height" - } - - @input_window_geometry = { - :top => "Ncurses.LINES - conf.input_height - 2", - :left => 0, - :width => "Ncurses.COLS", - :height => "conf.input_height + 2" - } - - @echo_keycodes = false - - @echo = true - - @show_level = :info - - @timestamp = false - - @connection_status = true - - # - # options to control what you see - # - - @disable_blink = false - - @timeformat = "%H:%M:%S" - - @broken_keycodes = { - 13 => true - } - - @max_history = 100 - - @default_attributes = Ncurses.const_get("A_NORMAL") - @default_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] - - @echo_attributes = Ncurses.const_get("A_BOLD") - @echo_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] - - @trace_attributes = Ncurses.const_get("A_NORMAL") - @trace_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] - - @debug_attributes = Ncurses.const_get("A_NORMAL") - @debug_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] - - @info_attributes = Ncurses.const_get("A_NORMAL") - @info_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] - - @warn_attributes = Ncurses.const_get("A_NORMAL") - @warn_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] - - @error_attributes = Ncurses.const_get("A_NORMAL") - @error_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] - - @flush = true - - @gags = [] - - @anti_gags = [] - - @remote_substitutions = {} - - @local_substitutions = {} - - # - # options to control what gets run when # - # - - @startup_triggers = [] - - @connect_triggers = [] - - @shutdown_triggers = [] - - @remote_triggers = {} - - @remote_character_triggers = {} - - @local_triggers = { - /^\/(.*)\n$/m => :execute_command!, - /^!(.*)\n$/m => :shell_command!, - /^#.*\n$/m => :ignore_command! - } - - @key_commands = { - 12 => :resize_application!, # ctrl-l - Ncurses.const_get("KEY_PPAGE") => :scroll_up!, - Ncurses.const_get("KEY_NPAGE") => :scroll_down!, - Ncurses.const_get("KEY_ENTER") => :process_buffer!, - 10 => :process_buffer!, # enter - 3 => :two_step_quit!, # ctrl-c - 9 => :complete!, # tab - 18 => :toggle_history_search!, # ctrl-r - 127 => :backspace_buffer!, # backspace - Ncurses.const_get("KEY_BACKSPACE") => :backspace_buffer!, - 27 => { - 263 => :word_backspace_buffer!, # alt-backspace - 91 => { - 49 => { - 59 => { - 53 => { - 68 => :previous_word_buffer!, # ctrl-key_left - 67 => :next_word_buffer!, # ctrl-key_right - } - } - } - } - }, - Ncurses.const_get("KEY_DC") => :delete_buffer!, - Ncurses.const_get("KEY_UP") => :previous_history_buffer!, - Ncurses.const_get("KEY_DOWN") => :next_history_buffer!, - 262 => :home_buffer!, # home_key - 360 => :end_buffer!, # end_key - Ncurses.const_get("KEY_LEFT") => :previous_character_buffer!, - Ncurses.const_get("KEY_RIGHT") => :next_character_buffer!, - 22 => :toggle_verbosity!, # ctrl-v - 265 => :help # f1 - } - - # - # miscellaneous options # - # - - @connect_timeout = 10 - - @feed_completer_with_history = true - - @feed_completer_with_input = true - - @extra_completions = [] - - @loaded_rc_file = false - - @user_edited_config_file = false - - @userdir = File.join(ENV["HOME"], "mubyrc.d") - - @history_file = File.join(@userdir, "history") - - @output_buffer = 1000 - - @input_height = 3 - - @input_logfile = nil - - @output_logfile = nil - - end - - # - # The magical method that lets us get and set the settings without - # having to write getters and setters for all of them - # - def method_missing(*args) - method_name = args[0].to_s - var_name = method_name[/^[^=]*/] - - setter = method_name =~ /=$/ - if setter - return super unless args.size == 2 - instance_variable_set("@#{var_name}", args[1]) - return args[1] - else - return super unless args.size == 1 - return instance_variable_get("@#{var_name}") - end - end - - # - # The halfway magical method that toggles all settings covered in - # @extra_verbosity_settings to what they are in that hash, - # and then stores them away inside the same hash for back-toggling again. - # - def toggle_verbosity! - - # copy old extra-settings to a copy - settings_copy = @extra_verbosity_settings.clone - - # set our extra-settings to be the currently applied settings - @extra_verbosity_settings.clone.each do |key, value| - @extra_verbosity_settings[key] = self.send(key) - end - - # apply the extra-settings - settings_copy.each do |key, value| - self.send("#{key}=", value) - end - - Muby::Displayer.info("Toggled verbosity. Press again to toggle back.") - end - - # - # Returns true if we are supposed to display messages - # of +level+. - # - def display?(level) - levels = [:trace, :debug, :info, :warn, :error] - levels.index(level) >= (levels.index(@show_level) || 0) - end - - # - # Will save the current configuration to the loaded rc file, - # or to mubyrc if no such file was loaded. - # - def save_configuration_file! - to_save = @loaded_rc_file ? @loaded_rc_file : File.join(ENV["HOME"], "mubyrc") - begin - Kernel::open(to_save, "w") do |output| - output.write(self.to_ruby) - @loaded_rc_file = to_save - end - Muby::Displayer.info("Saved default configuration to #{to_save}.") - rescue Exception => e - Muby::Displayer.warn("Failed saving default configuration to #{to_save}: #{e.message}") - Muby::Displayer.debug(e.backtrace.join("\n")) - end - end - - # - # Tries to load all the users files, defined as - # any file named .mubyrc or mubyrc in the users ENV["HOME"] - # and all **/*.rb files in the users ENV["HOME"]/@userdir - # with the root of the userdir taking precidence over subdirectories. - # Directories starting with a . are ignored. - # - # If none of the mubyrc-files existed, it will try to create one - # for the user to edit to his/her liking. - # - def load_user_files! - @loaded_rc_file = false - if to_load = [".mubyrc", "mubyrc"].collect do |file_name| - File.join(ENV["HOME"], file_name) - end.find do |file_name| - File.exists?(file_name) - end - nice_load!(to_load) - @loaded_rc_file = to_load - end - - unless @loaded_rc_file - save_configuration_file! - end - - if File.exists?(@userdir) - # Only load *.rb files within sub-directories of the current directory, and not the current directory's *.rb files!) - # Test: Dir[File.join(Dir.pwd, "*", "**", "*.rb")].each do |f| puts f end ; nil - Dir[File.join(@userdir, "*", "**", "*.rb")].each do |file_name| - nice_load!(file_name) - end - # Only load *.rb files of the current directory. - # This is very useful for users to create "overrides" for items in subdirectories. - # NOTE: This does follow symbolic links (files and directories) - # Test: Dir[File.join(Dir.pwd, "*.rb")].each do |f| puts f end ; nil - Dir[File.join(@userdir, "*.rb")].each do |file_name| - nice_load!(file_name) - end - else - Muby::Displayer.warn("#{@userdir} does not exist. If it did, *.rb in it would be loaded now.") - end - end - - # - # A non-raising method that tries to load +f+ and tells the output window about its success. - # - def nice_load!(f) - begin - Kernel::load(f) - Muby::Displayer.info("Loaded #{f}") - rescue Exception => e - Muby::Displayer.exception(e) - end - end - - # - # Will reload the entire app, ie the class files and the - # user files. - # - # TODO: Remove the spammyness. - # It is not appropriate to use 'puts' when reload_application! is being called by the user. - # To turn off "uninitialised constant" warnings, do: $VERBOSE = nil - # - # Simply set your show_level to :warn instead of :info, and you wont see the load messages. - # - # Any other messages come from your own files :O - # - def reload_application! - Dir[File.join(File.dirname(__FILE__), "**", "*.rb")].each do |file_name| - nice_load! file_name - end - load_user_files! - end - - # - # The not so magical at all method that prints our content - # to a String so that we easily can save our current settings - # in a file, or create a default config file. - # - def to_ruby - "# -# This is the default configuration of muby. -# To learn more about how to configure it, you -# can type '/help' in the client. -# -include Muby::Configurable -" + - instance_variables.sort.collect do |var_name| - value = eval(var_name) - case value - when Hash - space = "conf.#{var_name[1..-1]} = _".size - value = value.inspect.gsub(/, /, ",\n#{" " * space}") - when File - begin - value.read(0) - value = "open(\"#{value.path}\", \"r\")" - rescue - value = "open(\"#{value.path}\", \"a\")" - end - when NilClass - value = value.inspect - else - value = value.inspect - end - var_name = var_name[1..-1] - help_text = Muby::Help.configuration[var_name.to_sym] || "no help available for #{var_name}" - help_text = help_text.split("\n").join("\n# ") - " -# #{help_text} -conf.#{var_name} = #{value}" - end.join("\n") - end - - end - - # - # The module that provides the shorthand for - # using classes. - # - module Configurable - def conf - Configuration.get - end - end - -end Copied: tags/release_0_7_8/lib/muby/configuration.rb (from rev 268, trunk/lib/muby/configuration.rb) =================================================================== --- tags/release_0_7_8/lib/muby/configuration.rb (rev 0) +++ tags/release_0_7_8/lib/muby/configuration.rb 2008-05-24 00:45:04 UTC (rev 269) @@ -0,0 +1,389 @@ + +require 'ncurses' + +module Muby + + + VERSION = "0.7.8" unless defined?(Muby::VERSION) + + # + # The class that encapsulates all configuration. + # + # To simplify its use, include Muby::Configurable in your class. + # Then you can access Configuration as 'conf' (nice shorthand :) + # + # All options in Configuration are get'able and set'able. + # + # Look in help.rb to get the meaning of them. + # + class Configuration + + @@instance ||= nil + + def self.get + @@instance ||= Configuration.new + end + + def initialize + # + # verbosity options + # + + @extra_verbosity_settings = { + :echo_keycodes => true, + :echo => true, + :show_level => :debug, + :timestamp => true, + :connection_status => true + } + + @output_window_geometry = { + :top => 0, + :left => 0, + :width => "Ncurses.COLS", + :height => "Ncurses.LINES - Muby::InputWindow.get_instance.height" + } + + @input_window_geometry = { + :top => "Ncurses.LINES - conf.input_height - 2", + :left => 0, + :width => "Ncurses.COLS", + :height => "conf.input_height + 2" + } + + @echo_keycodes = false + + @echo = true + + @show_level = :info + + @timestamp = false + + @connection_status = true + + # + # options to control what you see + # + + @disable_blink = false + + @timeformat = "%H:%M:%S" + + @broken_keycodes = { + 13 => true + } + + @max_history = 100 + + @default_attributes = Ncurses.const_get("A_NORMAL") + @default_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] + + @echo_attributes = Ncurses.const_get("A_BOLD") + @echo_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] + + @trace_attributes = Ncurses.const_get("A_NORMAL") + @trace_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] + + @debug_attributes = Ncurses.const_get("A_NORMAL") + @debug_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] + + @info_attributes = Ncurses.const_get("A_NORMAL") + @info_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] + + @warn_attributes = Ncurses.const_get("A_NORMAL") + @warn_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] + + @error_attributes = Ncurses.const_get("A_NORMAL") + @error_colors = [Ncurses.const_get("COLOR_WHITE"), Ncurses.const_get("COLOR_BLACK")] + + @flush = true + + @gags = [] + + @anti_gags = [] + + @remote_substitutions = {} + + @local_substitutions = {} + + # + # options to control what gets run when # + # + + @startup_triggers = [] + + @connect_triggers = [] + + @shutdown_triggers = [] + + @remote_triggers = {} + + @remote_character_triggers = {} + + @local_triggers = { + /^\/(.*)\n$/m => :execute_command!, + /^!(.*)\n$/m => :shell_command!, + /^#.*\n$/m => :ignore_command! + } + + @key_commands = { + 12 => :resize_application!, # ctrl-l + Ncurses.const_get("KEY_PPAGE") => :scroll_up!, + Ncurses.const_get("KEY_NPAGE") => :scroll_down!, + Ncurses.const_get("KEY_ENTER") => :process_buffer!, + 10 => :process_buffer!, # enter + 3 => :two_step_quit!, # ctrl-c + 9 => :complete!, # tab + 18 => :toggle_history_search!, # ctrl-r + 127 => :backspace_buffer!, # backspace + Ncurses.const_get("KEY_BACKSPACE") => :backspace_buffer!, + 27 => { + 263 => :word_backspace_buffer!, # alt-backspace + 91 => { + 49 => { + 59 => { + 53 => { + 68 => :previous_word_buffer!, # ctrl-key_left + 67 => :next_word_buffer!, # ctrl-key_right + } + } + } + } + }, + Ncurses.const_get("KEY_DC") => :delete_buffer!, + Ncurses.const_get("KEY_UP") => :previous_history_buffer!, + Ncurses.const_get("KEY_DOWN") => :next_history_buffer!, + 262 => :home_buffer!, # home_key + 360 => :end_buffer!, # end_key + Ncurses.const_get("KEY_LEFT") => :previous_character_buffer!, + Ncurses.const_get("KEY_RIGHT") => :next_character_buffer!, + 22 => :toggle_verbosity!, # ctrl-v + 265 => :help # f1 + } + + # + # miscellaneous options # + # + + @connect_timeout = 10 + + @feed_completer_with_history = true + + @feed_completer_with_input = true + + @extra_completions = [] + + @loaded_rc_file = false + + @user_edited_config_file = false + + @userdir = File.join(ENV["HOME"], "mubyrc.d") + + @history_file = File.join(@userdir, "history") + + @output_buffer = 1000 + + @input_height = 3 + + @input_logfile = nil + + @output_logfile = nil + + end + + # + # The magical method that lets us get and set the settings without + # having to write getters and setters for all of them + # + def method_missing(*args) + method_name = args[0].to_s + var_name = method_name[/^[^=]*/] + + setter = method_name =~ /=$/ + if setter + return super unless args.size == 2 + instance_variable_set("@#{var_name}", args[1]) + return args[1] + else + return super unless args.size == 1 + return instance_variable_get("@#{var_name}") + end + end + + # + # The halfway magical method that toggles all settings covered in + # @extra_verbosity_settings to what they are in that hash, + # and then stores them away inside the same hash for back-toggling again. + # + def toggle_verbosity! + + # copy old extra-settings to a copy + settings_copy = @extra_verbosity_settings.clone + + # set our extra-settings to be the currently applied settings + @extra_verbosity_settings.clone.each do |key, value| + @extra_verbosity_settings[key] = self.send(key) + end + + # apply the extra-settings + settings_copy.each do |key, value| + self.send("#{key}=", value) + end + + Muby::Displayer.info("Toggled verbosity. Press again to toggle back.") + end + + # + # Returns true if we are supposed to display messages + # of +level+. + # + def display?(level) + levels = [:trace, :debug, :info, :warn, :error] + levels.index(level) >= (levels.index(@show_level) || 0) + end + + # + # Will save the current configuration to the loaded rc file, + # or to mubyrc if no such file was loaded. + # + def save_configuration_file! + to_save = @loaded_rc_file ? @loaded_rc_file : File.join(ENV["HOME"], "mubyrc") + begin + Kernel::open(to_save, "w") do |output| + output.write(self.to_ruby) + @loaded_rc_file = to_save + end + Muby::Displayer.info("Saved default configuration to #{to_save}.") + rescue Exception => e + Muby::Displayer.warn("Failed saving default configuration to #{to_save}: #{e.message}") + Muby::Displayer.debug(e.backtrace.join("\n")) + end + end + + # + # Tries to load all the users files, defined as + # any file named .mubyrc or mubyrc in the users ENV["HOME"] + # and all **/*.rb files in the users ENV["HOME"]/@userdir + # with the root of the userdir taking precidence over subdirectories. + # Directories starting with a . are ignored. + # + # If none of the mubyrc-files existed, it will try to create one + # for the user to edit to his/her liking. + # + def load_user_files! + @loaded_rc_file = false + if to_load = [".mubyrc", "mubyrc"].collect do |file_name| + File.join(ENV["HOME"], file_name) + end.find do |file_name| + File.exists?(file_name) + end + nice_load!(to_load) + @loaded_rc_file = to_load + end + + unless @loaded_rc_file + save_configuration_file! + end + + if File.exists?(@userdir) + # Only load *.rb files within sub-directories of the current directory, and not the current directory's *.rb files!) + # Test: Dir[File.join(Dir.pwd, "*", "**", "*.rb")].each do |f| puts f end ; nil + Dir[File.join(@userdir, "*", "**", "*.rb")].each do |file_name| + nice_load!(file_name) + end + # Only load *.rb files of the current directory. + # This is very useful for users to create "overrides" for items in subdirectories. + # NOTE: This does follow symbolic links (files and directories) + # Test: Dir[File.join(Dir.pwd, "*.rb")].each do |f| puts f end ; nil + Dir[File.join(@userdir, "*.rb")].each do |file_name| + nice_load!(file_name) + end + else + Muby::Displayer.warn("#{@userdir} does not exist. If it did, *.rb in it would be loaded now.") + end + end + + # + # A non-raising method that tries to load +f+ and tells the output window about its success. + # + def nice_load!(f) + begin + Kernel::load(f) + Muby::Displayer.info("Loaded #{f}") + rescue Exception => e + Muby::Displayer.exception(e) + end + end + + # + # Will reload the entire app, ie the class files and the + # user files. + # + # TODO: Remove the spammyness. + # It is not appropriate to use 'puts' when reload_application! is being called by the user. + # To turn off "uninitialised constant" warnings, do: $VERBOSE = nil + # + # Simply set your show_level to :warn instead of :info, and you wont see the load messages. + # + # Any other messages come from your own files :O + # + def reload_application! + Dir[File.join(File.dirname(__FILE__), "**", "*.rb")].each do |file_name| + nice_load! file_name + end + load_user_files! + end + + # + # The not so magical at all method that prints our content + # to a String so that we easily can save our current settings + # in a file, or create a default config file. + # + def to_ruby + "# +# This is the default configuration of muby. +# To learn more about how to configure it, you +# can type '/help' in the client. +# +include Muby::Configurable +" + + instance_variables.sort.collect do |var_name| + value = eval(var_name) + case value + when Hash + space = "conf.#{var_name[1..-1]} = _".size + value = value.inspect.gsub(/, /, ",\n#{" " * space}") + when File + begin + value.read(0) + value = "open(\"#{value.path}\", \"r\")" + rescue + value = "open(\"#{value.path}\", \"a\")" + end + when NilClass + value = value.inspect + else + value = value.inspect + end + var_name = var_name[1..-1] + help_text = Muby::Help.configuration[var_name.to_sym] || "no help available for #{var_name}" + help_text = help_text.split("\n").join("\n# ") + " +# #{help_text} +conf.#{var_name} = #{value}" + end.join("\n") + end + + end + + # + # The module that provides the shorthand for + # using classes. + # + module Configurable + def conf + Configuration.get + end + end + +end Deleted: tags/release_0_7_8/lib/muby/connection.rb =================================================================== --- trunk/lib/muby/connection.rb 2008-05-23 08:52:14 UTC (rev 267) +++ tags/release_0_7_8/lib/muby/connection.rb 2008-05-24 00:45:04 UTC (rev 269) @@ -1,397 +0,0 @@ - -require 'socket' - -# -# The class that encapsulates the actual Connection -# -class Muby::Connection - - include Muby::Logger - include Muby::Configurable - include Muby::Displayer - - # - # Set it up with windows, handle and host info. - # - def initialize(inputWindow, outputWindow, host, port) - @inputWindow = inputWindow - @outputWindow = outputWindow - status("Connecting to " + host.inspect + ":" + port.inspect) - @host = host - @port = port - connect! - conf.connect_triggers.each do |command| - @inputWindow.execute(command, @inputWindow, @outputWindow) - end - status("Connected to " + host.inspect + ":" + port.inspect) - @matchBuffer = "" - @showBuffer = [] - @used_triggers = {} - @listener = Thread.new do - begin - status("Listening thread started") - listen - status("Listening thread finished") - rescue Exception => e - exception(e) - ensure - close - end - end if @socket - end - - # - # Almost ripped from the documentation: http://www.ruby-doc.org/core/classes/Socket.src/M002114.html - # - def connect! - @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) - addr = Socket.sockaddr_in(@port, @host) - begin - @socket.connect_nonblock(addr) - rescue Errno::EINPROGRESS - IO.select(nil, [@socket], nil, conf.connect_timeout) - begin - @socket.connect_nonblock(addr) - rescue Errno::EISCONN - rescue Errno::EALREADY - raise "Connection timed out" - end - end - end - - # - # Display a status message in the outputwindow if wanted (conf.connection_status) - # - def status(message) - if conf.connection_status - @outputWindow.print_on_newline(*[message + "\n"]) - end - end - - # - # Check if we want to gag the current matchBuffer and debug about it. - # - # Remove the gag regexp if it is broken. - # - def gag(matchBuffer) - returnValue = false - conf.gags.each do |gag| - begin - if matchBuffer.match(gag) - trace(matchBuffer + " matches " + gag.inspect + ": gag active") - returnValue = true - end - rescue RegexpError => error - conf.gags.delete(key) - exception(e) - end - end - returnValue - end - - # - # Check if we should definitely NOT gag the current matchBuffer, and debug about it. - # - # Remove the nongag regexp if it is broken. - # - def nongag(matchBuffer) - returnValue = false - conf.anti_gags.each do |nongag| - begin - if matchBuffer.match(nongag) - trace(matchBuffer + " matches " + nongag.inspect + ": nongag active") - returnValue = true - end - rescue RegexpError => error - conf.anti_gags.delete(key) - exception(e) - end - end - returnValue - end - - # - # Check if we should trigger a Proc on the current matchBuffer, and debug about it. - # - # Remove the trigger regexp if it is broken. - # - def trigger(matchBuffer, hash, skip_used = true) - hash.each do |key, value| - if skip_used && @used_triggers.include?(key) - trace("#{key.inspect} has already been matched on this line, skipping it") - else - trace("checking if " + matchBuffer + " matches " + key.inspect) - begin - if match = matchBuffer.match(key) - trace(matchBuffer + " matches " + key.inspect + ": .call'ing Proc") - # Run the procedure associated with that trigger: - @inputWindow.execute(value, @inputWindow, @outputWindow, match) - @used_triggers[key] = true if skip_used - end - # If we received an error with the regular expression: - rescue RegexpError => error - hash.delete(key) - exception(error) - end - end - end - end - - def feed(s) - s.unpack("C*").each do |c| - handle(c) - end - nil - end - - def getc - c = @socket.getc - log_input(c.chr) if c - c - end - - TELNET_COMMANDS = { - 240 => :end_of_sub_negotiation, - 241 => :noop, - 242 => :data_mark, - 243 => :break, - 249 => :go_ahead, - 250 => :sub_negotiation, - 251 => :will, - 252 => :wont, - 253 => :do, - 254 => :dont, - 255 => :iac - } - - # - # This is not telnet command OR ansi, lets treat it as nice MUD text! - # - # Debug about it, add it to match buffer, add it to show buffer and show if we want to show. - # Then check it for triggers. - # - def handle_regular_character(c) - @matchBuffer = @matchBuffer + c.chr - append_show_buffer(c.chr) - manage_buffers(c) - end - - def handle(c) - # - # The telnet support (just so we dont explode or something) - # - # We are just plain ignoring most of it atm. - # - if TELNET_COMMANDS[c] == :iac # this is an "interpret as command" - c = getc - if (next_command = TELNET_COMMANDS[c]) == :iac # if the next one as well is an iac, we actually want to display a 255 - handle_regular_character(c) - else - case next_command - when :do # ignore the option negotiation - c = getc - when :dont # ignore the option negotiation - c = getc - when :will # ignore the option negotiation - c = getc - when :wont # ignore the option negotiation - c = getc - when :noop # waf? - # do nothing - when :data_mark - warn("Got a data_mark (TELNET protocol) which I don't know how to handle. Expect strange behaviour...") - when :break - warn("Got a break (TELNET protocol) which I don't know how to handle. Expect strange behaviour...") - when :go_ahead - display_buffer # on a go ahead the server obviously wants us to display the @displayBuffer regardless of our conf.flush setting - when :sub_negotiation # we just skip ahead to the end of the sub negotiation - while TELNET_COMMANDS[c] != :end_of_sub_negotiation - c = getc - end - else - warn("Got an unknown TELNET command (#{c.chr}) which I don't know how to handle. Expect strange behaviour...") - end - end - elsif c == 27 # escape char! this is probably some ANSI color or shite - c = getc - if c.chr == "[" # this is an ansi-something that is more than one char long - ansiString = "" - while !"cnRhl()HABCfsurhgKJipm".include?((c = getc).chr) - ansiString << c.chr - end - if c.chr == "m" && Ncurses.has_colors? # ah, text property! i understand this! - properties = ansiString.split(";") - attributes = 0 - bgcolor = false - fgcolor = false - reset = properties.index("0") - if reset - properties.delete("0") - end - properties.each do |property| - case property.to_i - when 1 - attributes = attributes | Ncurses.const_get("A_BOLD") - when 2 - attributes = attributes | Ncurses.const_get("A_DIM") - when 4 - attributes = attributes | Ncurses.const_get("A_UNDERLINE") - when 5 - attributes = attributes | Ncurses.const_get("A_BLINK") unless conf.disable_blink - when 7 - attributes = attributes | Ncurses.const_get("A_REVERSE") - when 8 - attributes = attributes | Ncurses.const_get("A_INVIS") - when 30 - fgcolor = Ncurses.const_get("COLOR_BLACK") - when 31 - fgcolor = Ncurses.const_get("COLOR_RED") - when 32 - fgcolor = Ncurses.const_get("COLOR_GREEN") - when 33 - fgcolor = Ncurses.const_get("COLOR_YELLOW") - when 34 - fgcolor = Ncurses.const_get("COLOR_BLUE") - when 35 - fgcolor = Ncurses.const_get("COLOR_MAGENTA") - when 36 - fgcolor = Ncurses.const_get("COLOR_CYAN") - when 37 - fgcolor = Ncurses.const_get("COLOR_WHITE") - when 40 - bgcolor = Ncurses.const_get("COLOR_BLACK") - when 41 - bgcolor = Ncurses.const_get("COLOR_RED") - when 42 - bgcolor = Ncurses.const_get("COLOR_GREEN") - when 43 - bgcolor = Ncurses.const_get("COLOR_YELLOW") - when 44 - bgcolor = Ncurses.const_get("COLOR_BLUE") - when 45 - bgcolor = Ncurses.const_get("COLOR_MAGENTA") - when 46 - bgcolor = Ncurses.const_get("COLOR_CYAN") - when 47 - bgcolor = Ncurses.const_get("COLOR_WHITE") - end - end - style = nil - if reset - style = Muby::Style.new(attributes, fgcolor, bgcolor, false) - else - style = Muby::Style.new(attributes, fgcolor, bgcolor, true) - end - @showBuffer.push(style) - end - end - elsif !conf.broken_keycodes.include?(c) - handle_regular_character(c) - end - end - - def append_show_buffer(c) - if String === @showBuffer.last - @showBuffer.last << c - else - @showBuffer << c - end - end - - # - # Keep listening to the remote socket and react accordingly. - # - def listen - c = true - # We have to look at each byte for ncurses reasons as well as triggers etc. - while c - while select([@socket],nil,nil,1) && c = getc - handle(c) - end - end - status("Connection closed by remote end") - @inputWindow.disconnect - end - - def close - if Thread.current != @listener && @listener && @listener.alive? - status("Killing listening thread") - @listener.kill - end - if @socket && !@socket.closed? - status("Disconnecting our end") - @socket.close if @socket - end - end - - def manage_buffers(c) - trigger(@matchBuffer, conf.remote_character_triggers, true) - if c == 10 || conf.flush - display_buffer - if c == 10 - trigger(@matchBuffer, conf.remote_triggers, false) - @matchBuffer = "" - @used_triggers = {} - end - end - end - - def homemade_split(s, r) - rval = [] - rest = s - while match = rest.match(/(.*?)#{r.source}(.*)/) - rval << match[1] - rest = match[2] - end - rval << rest - rval - end - - def substitute(buffer, hash) - return_value = [] - buffer.each do |part| - if String === part - part_to_append = [part] - hash.each do |regexp, substitution| - case substitution - when String - part_to_append = [part.gsub(regexp, substitution)] - when Array - if part.match(regexp) - split_part = homemade_split(part, regexp) - part_to_append = split_part.zip([substitution] * (split_part.size - 1)).flatten.compact - end - end - end - return_value += part_to_append - else - return_value << part - end - end - return_value - end - - def display_buffer - unless @showBuffer.empty? - if !gag(@matchBuffer) || nongag(@matchBuffer) - @showBuffer = substitute(@showBuffer, conf.remote_substitutions) - Muby::Completer.get_instance.store(@matchBuffer) if conf.feed_completer_with_input - @outputWindow.print(*@showBuffer) - end - @showBuffer = [] - end - end - - # - # Just plain send the string we got. - # - def send(s) - log_output(s) - conf.local_substitutions.each do |key, value| - # It might be useful to allow colour codes for highlighting local substitutions.. but only when echo is on. - # No, cause this only gets sent to the server, it never shows up to the user. - s.gsub!(key, value) - end - @socket.print(s) if @socket - end -end # class Connection Copied: tags/release_0_7_8/lib/muby/connection.rb (from rev 268, trunk/lib/muby/connection.rb) =================================================================== --- tags/release_0_7_8/lib/muby/connection.rb (rev 0) +++ tags/release_0_7_8/lib/muby/connection.rb 2008-05-24 00:45:04 UTC (rev 269) @@ -0,0 +1,399 @@ + +require 'socket' + +# +# The class that encapsulates the actual Connection +# +class Muby::Connection + + include Muby::Logger + include Muby::Configurable + include Muby::Displayer + + # + # Set it up with windows, handle and host info. + # + def initialize(inputWindow, outputWindow, host, port) + @inputWindow = inputWindow + @outputWindow = outputWindow + status("Connecting to " + host.inspect + ":" + port.inspect) + @host = host + @port = port + connect! + conf.connect_triggers.each do |command| + @inputWindow.execute(command, @inputWindow, @outputWindow) + end + status("Connected to " + host.inspect + ":" + port.inspect) + @matchBuffer = "" + @showBuffer = [] + @used_triggers = {} + @listener = Thread.new do + begin + status("Listening thread started") + listen + status("Listening thread finished") + rescue Exception => e + exception(e) + ensure + close + end + end if @socket + end + + # + # Almost ripped from the documentation: http://www.ruby-doc.org/core/classes/Socket.src/M002114.html + # + def connect! + @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) + addr = Socket.sockaddr_in(@port, @host) + begin + @socket.connect_nonblock(addr) + rescue Errno::EINPROGRESS + IO.select(nil, [@socket], nil, conf.connect_timeout) + begin + @socket.connect_nonblock(addr) + rescue Errno::EISCONN + rescue Errno::EALREADY + raise "Connection timed out" + end + end + end + + # + # Display a status message in the outputwindow if wanted (conf.connection_status) + # + def status(message) + if conf.connection_status + @outputWindow.print_on_newline(*[message + "\n"]) + end + end + + # + # Check if we want to gag the current matchBuffer and debug about it. + # + # Remove the gag regexp if it is broken. + # + def gag(matchBuffer) + returnValue = false + conf.gags.each do |gag| + begin + if matchBuffer.match(gag) + trace(matchBuffer + " matches " + gag.inspect + ": gag active") + returnValue = true + end + rescue RegexpError => error + conf.gags.delete(key) + exception(e) + end + end + returnValue + end + + # + # Check if we should definitely NOT gag the current matchBuffer, and debug about it. + # + # Remove the nongag regexp if it is broken. + # + def nongag(matchBuffer) + returnValue = false + conf.anti_gags.each do |nongag| + begin + if matchBuffer.match(nongag) + trace(matchBuffer + " matches " + nongag.inspect + ": nongag active") + returnValue = true + end + rescue RegexpError => error + conf.anti_gags.delete(key) + exception(e) + end + end + returnValue + end + + # + # Check if we should trigger a Proc on the current matchBuffer, and debug about it. + # + # Remove the trigger regexp if it is broken. + # + def trigger(matchBuffer, hash, skip_used = true) + hash.each do |key, value| + if skip_used && @used_triggers.include?(key) + trace("#{key.inspect} has already been matched on this line, skipping it") + else + trace("checking if " + matchBuffer + " matches " + key.inspect) + begin + if match = matchBuffer.match(key) + trace(matchBuffer + " matches " + key.inspect + ": .call'ing Proc") + # Run the procedure associated with that trigger: + @inputWindow.execute(value, @inputWindow, @outputWindow, match) + @used_triggers[key] = true if skip_used + end + # If we received an error with the regular expression: + rescue RegexpError => error + hash.delete(key) + exception(error) + end + end + end + end + + def feed(s) + s.unpack("C*").each do |c| + handle(c) + end + nil + end + + def getc + c = @socket.getc + log_input(c.chr) if c + c + end + + unless defined?(TELNET_COMMANDS) + TELNET_COMMANDS = { + 240 => :end_of_sub_negotiation, + 241 => :noop, + 242 => :data_mark, + 243 => :break, + 249 => :go_ahead, + 250 => :sub_negotiation, + 251 => :will, + 252 => :wont, + 253 => :do, + 254 => :dont, + 255 => :iac + } + end + + # + # This is not telnet command OR ansi, lets treat it as nice MUD text! + # + # Debug about it, add it to match buffer, add it to show buffer and show if we want to show. + # Then check it for triggers. + # + def handle_regular_character(c) + @matchBuffer = @matchBuffer + c.chr + append_show_buffer(c.chr) + manage_buffers(c) + end + + def handle(c) + # + # The telnet support (just so we dont explode or something) + # + # We are just plain ignoring most of it atm. + # + if TELNET_COMMANDS[c] == :iac # this is an "interpret as command" + c = getc + if (next_command = TELNET_COMMANDS[c]) == :iac # if the next one as well is an iac, we actually want to display a 255 + handle_regular_character(c) + else + case next_command + when :do # ignore the option negotiation + c = getc + when :dont # ignore the option negotiation + c = getc + when :will # ignore the option negotiation + c = getc + when :wont # ignore the option negotiation + c = getc + when :noop # waf? + # do nothing + when :data_mark + warn("Got a data_mark (TELNET protocol) which I don't know how to handle. Expect strange behaviour...") + when :break + warn("Got a break (TELNET protocol) which I don't know how to handle. Expect strange behaviour...") + when :go_ahead + display_buffer # on a go ahead the server obviously wants us to display the @displayBuffer regardless of our conf.flush setting + when :sub_negotiation # we just skip ahead to the end of the sub negotiation + while TELNET_COMMANDS[c] != :end_of_sub_negotiation + c = getc + end + else + warn("Got an unknown TELNET command (#{c.chr}) which I don't know how to handle. Expect strange behaviour...") + end + end + elsif c == 27 # escape char! this is probably some ANSI color or shite + c = getc + if c.chr == "[" # this is an ansi-something that is more than one char long + ansiString = "" + while !"cnRhl()HABCfsurhgKJipm".include?((c = getc).chr) + ansiString << c.chr + end + if c.chr == "m" && Ncurses.has_colors? # ah, text property! i understand this! + properties = ansiString.split(";") + attributes = 0 + bgcolor = false + fgcolor = false + reset = properties.index("0") + if reset + properties.delete("0") + end + properties.each do |property| + case property.to_i + when 1 + attributes = attributes | Ncurses.const_get("A_BOLD") + when 2 + attributes = attributes | Ncurses.const_get("A_DIM") + when 4 + attributes = attributes | Ncurses.const_get("A_UNDERLINE") + when 5 + attributes = attributes | Ncurses.const_get("A_BLINK") unless conf.disable_blink + when 7 + attributes = attributes | Ncurses.const_get("A_REVERSE") + when 8 + attributes = attributes | Ncurses.const_get("A_INVIS") + when 30 + fgcolor = Ncurses.const_get("COLOR_BLACK") + when 31 + fgcolor = Ncurses.const_get("COLOR_RED") + when 32 + fgcolor = Ncurses.const_get("COLOR_GREEN") + when 33 + fgcolor = Ncurses.const_get("COLOR_YELLOW") + when 34 + fgcolor = Ncurses.const_get("COLOR_BLUE") + when 35 + fgcolor = Ncurses.const_get("COLOR_MAGENTA") + when 36 + fgcolor = Ncurses.const_get("COLOR_CYAN") + when 37 + fgcolor = Ncurses.const_get("COLOR_WHITE") + when 40 + bgcolor = Ncurses.const_get("COLOR_BLACK") + when 41 + bgcolor = Ncurses.const_get("COLOR_RED") + when 42 + bgcolor = Ncurses.const_get("COLOR_GREEN") + when 43 + bgcolor = Ncurses.const_get("COLOR_YELLOW") + when 44 + bgcolor = Ncurses.const_get("COLOR_BLUE") + when 45 + bgcolor = Ncurses.const_get("COLOR_MAGENTA") + when 46 + bgcolor = Ncurses.const_get("COLOR_CYAN") + when 47 + bgcolor = Ncurses.const_get("COLOR_WHITE") + end + end + style = nil + if reset + style = Muby::Style.new(attributes, fgcolor, bgcolor, false) + else + style = Muby::Style.new(attributes, fgcolor, bgcolor, true) + end + @showBuffer.push(style) + end + end + elsif !conf.broken_keycodes.include?(c) + handle_regular_character(c) + end + end + + def append_show_buffer(c) + if String === @showBuffer.last + @showBuffer.last << c + else + @showBuffer << c + end + end + + # + # Keep listening to the remote socket and react accordingly. + # + def listen + c = true + # We have to look at each byte for ncurses reasons as well as triggers etc. + while c + while select([@socket],nil,nil,1) && c = getc + handle(c) + end + end + status("Connection closed by remote end") + @inputWindow.disconnect + end + + def close + if Thread.current != @listener && @listener && @listener.alive? + status("Killing listening thread") + @listener.kill + end + if @socket && !@socket.closed? + status("Disconnecting our end") + @socket.close if @socket + end + end + + def manage_buffers(c) + trigger(@matchBuffer, conf.remote_character_triggers, true) + if c == 10 || conf.flush + display_buffer + if c == 10 + trigger(@matchBuffer, conf.remote_triggers, false) + @matchBuffer = "" + @used_triggers = {} + end + end + end + + def homemade_split(s, r) + rval = [] + rest = s + while match = rest.match(/(.*?)#{r.source}(.*)/) + rval << match[1] + rest = match[2] + end + rval << rest + rval + end + + def substitute(buffer, hash) + return_value = [] + buffer.each do |part| + if String === part + part_to_append = [part] + hash.each do |regexp, substitution| + case substitution + when String + part_to_append = [part.gsub(regexp, substitution)] + when Array + if part.match(regexp) + split_part = homemade_split(part, regexp) + part_to_append = split_part.zip([substitution] * (split_part.size - 1)).flatten.compact + end + end + end + return_value += part_to_append + else + return_value << part + end + end + return_value + end + + def display_buffer + unless @showBuffer.empty? + if !gag(@matchBuffer) || nongag(@matchBuffer) + @showBuffer = substitute(@showBuffer, conf.remote_substitutions) + Muby::Completer.get_instance.store(@matchBuffer) if conf.feed_completer_with_input + @outputWindow.print(*@showBuffer) + end + @showBuffer = [] + end + end + + # + # Just plain send the string we got. + # + def send(s) + log_output(s) + conf.local_substitutions.each do |key, value| + # It might be useful to allow colour codes for highlighting local substitutions.. but only when echo is on. + # No, cause this only gets sent to the server, it never shows up to the user. + s.gsub!(key, value) + end + @socket.print(s) if @socket + end +end # class Connection