carats 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +2 -0
- data/LICENSE +5 -0
- data/README +67 -0
- data/Reapfile +72 -0
- data/ToDo +24 -0
- data/bench/b_harray.rb +49 -0
- data/bench/b_range.rb +64 -0
- data/demo/ansicolor/cdiff.rb +20 -0
- data/demo/ansicolor/example.rb +82 -0
- data/demo/io-reactor/chatserver.rb +347 -0
- data/doc/classes/Array.html +172 -0
- data/doc/classes/BBCode.html +638 -0
- data/doc/classes/BinaryReader.html +675 -0
- data/doc/classes/Binding.html +223 -0
- data/doc/classes/ByteOrder.html +284 -0
- data/doc/classes/Class.html +189 -0
- data/doc/classes/Constant.html +785 -0
- data/doc/classes/Constant/CGS.html +609 -0
- data/doc/classes/Continuation.html +113 -0
- data/doc/classes/Coroutine.html +387 -0
- data/doc/classes/CountingSemaphore.html +337 -0
- data/doc/classes/CrossCase.html +561 -0
- data/doc/classes/DynamicMixin.html +185 -0
- data/doc/classes/EnumerableWithArgs.html +550 -0
- data/doc/classes/Expect.html +428 -0
- data/doc/classes/Expect/DefaultChain.html +113 -0
- data/doc/classes/Expect/SeparatedPattern.html +223 -0
- data/doc/classes/Expect/Timeout.html +167 -0
- data/doc/classes/Expect/UnmatchedMessage.html +160 -0
- data/doc/classes/FileList.html +833 -0
- data/doc/classes/FloatString.html +534 -0
- data/doc/classes/Functor.html +211 -0
- data/doc/classes/HArray.html +1872 -0
- data/doc/classes/HTML.html +328 -0
- data/doc/classes/Heap.html +683 -0
- data/doc/classes/Heap/EmptyHeapException.html +111 -0
- data/doc/classes/Heap/Max.html +176 -0
- data/doc/classes/Heap/Min.html +176 -0
- data/doc/classes/IO.html +108 -0
- data/doc/classes/IO/Reactor.html +790 -0
- data/doc/classes/IO/Redirect.html +289 -0
- data/doc/classes/Infinity.html +320 -0
- data/doc/classes/Interval.html +1014 -0
- data/doc/classes/InvalidNackError.html +161 -0
- data/doc/classes/Kernel.html +204 -0
- data/doc/classes/Lisp.html +1132 -0
- data/doc/classes/Lisp/DottedPair.html +379 -0
- data/doc/classes/Lisp/Format.html +178 -0
- data/doc/classes/Lisp/Format/ArgumentError.html +126 -0
- data/doc/classes/Lisp/Format/Directives.html +155 -0
- data/doc/classes/Lisp/Format/Directives/ArgJump.html +178 -0
- data/doc/classes/Lisp/Format/Directives/Ascii.html +119 -0
- data/doc/classes/Lisp/Format/Directives/BeginCaseConversion.html +185 -0
- data/doc/classes/Lisp/Format/Directives/BeginConditional.html +307 -0
- data/doc/classes/Lisp/Format/Directives/BeginIteration.html +338 -0
- data/doc/classes/Lisp/Format/Directives/Binary.html +157 -0
- data/doc/classes/Lisp/Format/Directives/Character.html +228 -0
- data/doc/classes/Lisp/Format/Directives/CharacterDirective.html +203 -0
- data/doc/classes/Lisp/Format/Directives/ClauseSeparator.html +166 -0
- data/doc/classes/Lisp/Format/Directives/Decimal.html +119 -0
- data/doc/classes/Lisp/Format/Directives/Directive.html +397 -0
- data/doc/classes/Lisp/Format/Directives/DollarFP.html +205 -0
- data/doc/classes/Lisp/Format/Directives/EndCaseConversion.html +174 -0
- data/doc/classes/Lisp/Format/Directives/EndConditional.html +159 -0
- data/doc/classes/Lisp/Format/Directives/EndIteration.html +163 -0
- data/doc/classes/Lisp/Format/Directives/ExpFP.html +252 -0
- data/doc/classes/Lisp/Format/Directives/FFFP.html +224 -0
- data/doc/classes/Lisp/Format/Directives/Factory.html +180 -0
- data/doc/classes/Lisp/Format/Directives/FreshLine.html +175 -0
- data/doc/classes/Lisp/Format/Directives/GeneralFP.html +265 -0
- data/doc/classes/Lisp/Format/Directives/Hexadecimal.html +157 -0
- data/doc/classes/Lisp/Format/Directives/Indirection.html +183 -0
- data/doc/classes/Lisp/Format/Directives/Literal.html +187 -0
- data/doc/classes/Lisp/Format/Directives/NewLine.html +158 -0
- data/doc/classes/Lisp/Format/Directives/NewPage.html +158 -0
- data/doc/classes/Lisp/Format/Directives/Number.html +243 -0
- data/doc/classes/Lisp/Format/Directives/Octal.html +157 -0
- data/doc/classes/Lisp/Format/Directives/Plural.html +177 -0
- data/doc/classes/Lisp/Format/Directives/Print.html +237 -0
- data/doc/classes/Lisp/Format/Directives/Radix.html +432 -0
- data/doc/classes/Lisp/Format/Directives/SExpression.html +157 -0
- data/doc/classes/Lisp/Format/Directives/SkipWhitespace.html +165 -0
- data/doc/classes/Lisp/Format/Directives/Tabulate.html +198 -0
- data/doc/classes/Lisp/Format/Directives/Tilde.html +158 -0
- data/doc/classes/Lisp/Format/Directives/UnknownDirectiveError.html +117 -0
- data/doc/classes/Lisp/Format/Formatter.html +193 -0
- data/doc/classes/Lisp/Format/IncompleteParameterError.html +119 -0
- data/doc/classes/Lisp/Format/IndexError.html +126 -0
- data/doc/classes/Lisp/Format/Lexer.html +479 -0
- data/doc/classes/Lisp/Format/MalformedError.html +119 -0
- data/doc/classes/Lisp/Format/MissingParameterError.html +119 -0
- data/doc/classes/Lisp/Format/ModifierError.html +119 -0
- data/doc/classes/Lisp/Format/Output.html +239 -0
- data/doc/classes/Lisp/Format/ParameterError.html +126 -0
- data/doc/classes/Lisp/Format/Parameters.html +123 -0
- data/doc/classes/Lisp/Format/Parameters/Argument.html +172 -0
- data/doc/classes/Lisp/Format/Parameters/ArgumentCount.html +159 -0
- data/doc/classes/Lisp/Format/Parameters/Character.html +119 -0
- data/doc/classes/Lisp/Format/Parameters/Default.html +120 -0
- data/doc/classes/Lisp/Format/Parameters/Integer.html +119 -0
- data/doc/classes/Lisp/Format/Parameters/Parameter.html +206 -0
- data/doc/classes/Lisp/Format/Parser.html +212 -0
- data/doc/classes/Lisp/Format/Positioned.html +166 -0
- data/doc/classes/Lisp/Format/State.html +455 -0
- data/doc/classes/Lisp/Format/SyntaxError.html +126 -0
- data/doc/classes/Method.html +274 -0
- data/doc/classes/Method/DuckHunter.html +281 -0
- data/doc/classes/Module.html +709 -0
- data/doc/classes/Multiton.html +284 -0
- data/doc/classes/Multiton/New.html +164 -0
- data/doc/classes/Multiton/Semi.html +155 -0
- data/doc/classes/NackClass.html +322 -0
- data/doc/classes/NilClass.html +231 -0
- data/doc/classes/NilComparable.html +179 -0
- data/doc/classes/NotCopyable.html +273 -0
- data/doc/classes/Object.html +261 -0
- data/doc/classes/OpenStructable.html +346 -0
- data/doc/classes/OrderedHash.html +939 -0
- data/doc/classes/Parser.html +515 -0
- data/doc/classes/Parser/Main.html +178 -0
- data/doc/classes/Parser/Marker.html +475 -0
- data/doc/classes/Parser/Registry.html +354 -0
- data/doc/classes/Parser/Token.html +399 -0
- data/doc/classes/Parser/UnitToken.html +222 -0
- data/doc/classes/Ref.html +230 -0
- data/doc/classes/SimpleStringIO.html +183 -0
- data/doc/classes/StaticHash.html +202 -0
- data/doc/classes/String.html +172 -0
- data/doc/classes/Struct.html +181 -0
- data/doc/classes/SuperStruct.html +382 -0
- data/doc/classes/Term.html +156 -0
- data/doc/classes/Term/ANSIColor.html +185 -0
- data/doc/classes/Text.html +138 -0
- data/doc/classes/Text/Soundex.html +222 -0
- data/doc/classes/TextTagIterator.html +911 -0
- data/doc/classes/Time.html +119 -0
- data/doc/classes/Time/Limit.html +303 -0
- data/doc/classes/Time/Limit/Dummy.html +181 -0
- data/doc/classes/Timer.html +351 -0
- data/doc/classes/TracePoint.html +532 -0
- data/doc/classes/Tuple.html +178 -0
- data/doc/classes/Uninheritable.html +213 -0
- data/doc/classes/Version.html +783 -0
- data/doc/created.rid +1 -0
- data/doc/files/LICENSE.html +113 -0
- data/doc/files/README.html +201 -0
- data/doc/files/lib/carat/1st_rb.html +107 -0
- data/doc/files/lib/carat/ansicolor_rb.html +146 -0
- data/doc/files/lib/carat/attr_rb.html +101 -0
- data/doc/files/lib/carat/bbcode_rb.html +152 -0
- data/doc/files/lib/carat/binaryreader_rb.html +114 -0
- data/doc/files/lib/carat/binding-of-caller_rb.html +108 -0
- data/doc/files/lib/carat/byteorder_rb.html +107 -0
- data/doc/files/lib/carat/constant_rb.html +167 -0
- data/doc/files/lib/carat/coroutine_rb.html +156 -0
- data/doc/files/lib/carat/crosscase_rb.html +224 -0
- data/doc/files/lib/carat/duckhunter_rb.html +165 -0
- data/doc/files/lib/carat/dynamic-mixin_rb.html +101 -0
- data/doc/files/lib/carat/enumerable-args_rb.html +140 -0
- data/doc/files/lib/carat/expect_rb.html +137 -0
- data/doc/files/lib/carat/filelist_rb.html +130 -0
- data/doc/files/lib/carat/floatstring_rb.html +126 -0
- data/doc/files/lib/carat/functor_rb.html +140 -0
- data/doc/files/lib/carat/harray_rb.html +128 -0
- data/doc/files/lib/carat/heap_rb.html +154 -0
- data/doc/files/lib/carat/html-helpers_rb.html +116 -0
- data/doc/files/lib/carat/infinity_rb.html +142 -0
- data/doc/files/lib/carat/init_rb.html +127 -0
- data/doc/files/lib/carat/interval_rb.html +162 -0
- data/doc/files/lib/carat/io-reactor_rb.html +211 -0
- data/doc/files/lib/carat/io-redirect_rb.html +132 -0
- data/doc/files/lib/carat/lisp-format_rb.html +187 -0
- data/doc/files/lib/carat/lisp_rb.html +152 -0
- data/doc/files/lib/carat/macro_rb.html +129 -0
- data/doc/files/lib/carat/multiton_rb.html +178 -0
- data/doc/files/lib/carat/nack_rb.html +193 -0
- data/doc/files/lib/carat/nil-comparable_rb.html +126 -0
- data/doc/files/lib/carat/nil-missing_rb.html +101 -0
- data/doc/files/lib/carat/notcopyable_rb.html +166 -0
- data/doc/files/lib/carat/orderedhash_rb.html +107 -0
- data/doc/files/lib/carat/ostructable_rb.html +157 -0
- data/doc/files/lib/carat/parser-old_rb.html +239 -0
- data/doc/files/lib/carat/parser_rb.html +244 -0
- data/doc/files/lib/carat/ref_rb.html +107 -0
- data/doc/files/lib/carat/semaphore_rb.html +132 -0
- data/doc/files/lib/carat/snapshot_rb.html +152 -0
- data/doc/files/lib/carat/soundex_rb.html +128 -0
- data/doc/files/lib/carat/sstruct_rb.html +142 -0
- data/doc/files/lib/carat/statichash_rb.html +150 -0
- data/doc/files/lib/carat/tagiter_rb.html +236 -0
- data/doc/files/lib/carat/timelimit_rb.html +136 -0
- data/doc/files/lib/carat/timer_rb.html +153 -0
- data/doc/files/lib/carat/tracepoint_rb.html +160 -0
- data/doc/files/lib/carat/tuple_rb.html +123 -0
- data/doc/files/lib/carat/uninheritable_rb.html +101 -0
- data/doc/files/lib/carat/version_rb.html +141 -0
- data/doc/fr_class_index.html +159 -0
- data/doc/fr_file_index.html +78 -0
- data/doc/fr_method_index.html +663 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/carat-dev/README +11 -0
- data/lib/carat-dev/access-blocks/access_blocks.rb +42 -0
- data/lib/carat-dev/association/association.rb +70 -0
- data/lib/carat-dev/blankslate/blankslate.rb +51 -0
- data/lib/carat-dev/breakpoint.rb +518 -0
- data/lib/carat-dev/class-constructor/constructor_methods.rb +78 -0
- data/lib/carat-dev/class-constructor/tc_constructor.rb +35 -0
- data/lib/carat-dev/closecall/closecall-test.rb +39 -0
- data/lib/carat-dev/closecall/closecall.rb +101 -0
- data/lib/carat-dev/commandrunner/commandrunner.rb +100 -0
- data/lib/carat-dev/conditional/conditionals.rb +106 -0
- data/lib/carat-dev/daemon/daemon.rb +70 -0
- data/lib/carat-dev/detach/detach.rb +363 -0
- data/lib/carat-dev/detach/tc_detach.rb +57 -0
- data/lib/carat-dev/import-module/import-module-0.81.tar.gz +0 -0
- data/lib/carat-dev/import-module/import-module-0.81/LICENSE +1 -0
- data/lib/carat-dev/import-module/import-module-0.81/Makefile +11 -0
- data/lib/carat-dev/import-module/import-module-0.81/README +4 -0
- data/lib/carat-dev/import-module/import-module-0.81/dev-lib/import-module-hash.rb +49 -0
- data/lib/carat-dev/import-module/import-module-0.81/dev-lib/import-module-pip.rb +71 -0
- data/lib/carat-dev/import-module/import-module-0.81/dev-lib/import-module-unbound-method.rb +36 -0
- data/lib/carat-dev/import-module/import-module-0.81/doc/README-ja.html +293 -0
- data/lib/carat-dev/import-module/import-module-0.81/doc/README-ja.rd +306 -0
- data/lib/carat-dev/import-module/import-module-0.81/doc/README.html +290 -0
- data/lib/carat-dev/import-module/import-module-0.81/doc/README.rd +303 -0
- data/lib/carat-dev/import-module/import-module-0.81/doc/style.css +85 -0
- data/lib/carat-dev/import-module/import-module-0.81/install.rb +99 -0
- data/lib/carat-dev/import-module/import-module-0.81/lib/import-module-single-thread.rb +84 -0
- data/lib/carat-dev/import-module/import-module-0.81/lib/import-module.rb +493 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/Makefile +2 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/test +91 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/test-import-module.rb +936 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/test-import_scope.rb +33 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/test-scope_import.rb +33 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/test-time.rb +184 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/test.sh +91 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/time.rb +135 -0
- data/lib/carat-dev/import-module/import-module-0.81/test/times-do.sh +10 -0
- data/lib/carat-dev/interface_work/SCRAP/i-contracts.rb +37 -0
- data/lib/carat-dev/interface_work/SCRAP/interface.rb +105 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0.zip +0 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/CHANGES +3 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/MANIFEST +15 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/README +32 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/doc/interface.rd +73 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/doc/interface.txt +94 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/install.rb +16 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/lib/interface.rb +50 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/test/tc_interface.rb +51 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/test/test.rb +29 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/test/test_instance.rb +24 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/test/test_sub.rb +29 -0
- data/lib/carat-dev/interface_work/SCRAP/j-interface/interface-0.1.0/test/test_unrequire.rb +28 -0
- data/lib/carat-dev/interface_work/contracts/contract.zip +0 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract.html +376 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract.src/M000001.html +23 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract.src/M000002.html +18 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract.src/M000003.html +19 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract.src/M000004.html +29 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract.src/M000005.html +18 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract.src/M000006.html +18 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract/ContractError.html +142 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract/ContractException.html +153 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Contract/ContractMismatch.html +125 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Module.html +157 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/classes/Module.src/M000007.html +112 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/created.rid +1 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/files/lib/contract/assertions_rb.html +109 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/files/lib/contract/exception_rb.html +108 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/files/lib/contract/integration_rb.html +108 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/files/lib/contract/overrides_rb.html +109 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/files/lib/contract_rb.html +114 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/fr_class_index.html +31 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/fr_file_index.html +31 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/fr_method_index.html +33 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/index.html +24 -0
- data/lib/carat-dev/interface_work/contracts/contract/doc/rdoc-style.css +208 -0
- data/lib/carat-dev/interface_work/contracts/contract/lib/contract.rb +88 -0
- data/lib/carat-dev/interface_work/contracts/contract/lib/contract/assertions.rb +37 -0
- data/lib/carat-dev/interface_work/contracts/contract/lib/contract/exception.rb +92 -0
- data/lib/carat-dev/interface_work/contracts/contract/lib/contract/integration.rb +132 -0
- data/lib/carat-dev/interface_work/contracts/contract/lib/contract/overrides.rb +32 -0
- data/lib/carat-dev/interface_work/must.rb +37 -0
- data/lib/carat-dev/interface_work/type.rb +232 -0
- data/lib/carat-dev/main/tc_toplevel.rb +23 -0
- data/lib/carat-dev/main/toplevel.rb +33 -0
- data/lib/carat-dev/main/toplevel_test.rb +24 -0
- data/lib/carat-dev/misc/1.rb +40 -0
- data/lib/carat-dev/misc/misc.rb +44 -0
- data/lib/carat-dev/misc/sys.rb +186 -0
- data/lib/carat-dev/misc/temp.rb +1 -0
- data/lib/carat-dev/misc/utils.rb +518 -0
- data/lib/carat-dev/predicate/predicate.rb +109 -0
- data/lib/carat-dev/predicate/predicate_test.rb +67 -0
- data/lib/carat-dev/premshree.rb +40 -0
- data/lib/carat-dev/priority-queue/pqueue.rb +183 -0
- data/lib/carat-dev/priority-queue/priorityqueue.rb +84 -0
- data/lib/carat-dev/quaternion/quaternion.rb +529 -0
- data/lib/carat-dev/range.rb +259 -0
- data/lib/carat-dev/system/rubyinfo.rb +75 -0
- data/lib/carat-dev/system/system.rb +105 -0
- data/lib/carat-dev/tc_range.rb +118 -0
- data/lib/carat-dev/timer/timer-doc/classes/Timer.html +291 -0
- data/lib/carat-dev/timer/timer-doc/classes/Timer.src/M000001.html +26 -0
- data/lib/carat-dev/timer/timer-doc/classes/Timer.src/M000002.html +19 -0
- data/lib/carat-dev/timer/timer-doc/classes/Timer.src/M000003.html +18 -0
- data/lib/carat-dev/timer/timer-doc/classes/Timer.src/M000004.html +18 -0
- data/lib/carat-dev/timer/timer-doc/classes/Timer.src/M000005.html +21 -0
- data/lib/carat-dev/timer/timer-doc/classes/Timer.src/M000006.html +23 -0
- data/lib/carat-dev/timer/timer-doc/created.rid +1 -0
- data/lib/carat-dev/timer/timer-doc/files/timer_rb.html +144 -0
- data/lib/carat-dev/timer/timer-doc/fr_class_index.html +27 -0
- data/lib/carat-dev/timer/timer-doc/fr_file_index.html +27 -0
- data/lib/carat-dev/timer/timer-doc/fr_method_index.html +32 -0
- data/lib/carat-dev/timer/timer-doc/index.html +24 -0
- data/lib/carat-dev/timer/timer-doc/rdoc-style.css +208 -0
- data/lib/carat-dev/timer/timer.rb +160 -0
- data/lib/carat-dev/vars/vars.rb +62 -0
- data/lib/carat/1st.rb +58 -0
- data/lib/carat/ansicolor.rb +122 -0
- data/lib/carat/attr.rb +342 -0
- data/lib/carat/bbcode.rb +352 -0
- data/lib/carat/binaryreader.rb +170 -0
- data/lib/carat/binding-of-caller.rb +83 -0
- data/lib/carat/byteorder.rb +34 -0
- data/lib/carat/constant.rb +287 -0
- data/lib/carat/coroutine.rb +102 -0
- data/lib/carat/crosscase.rb +309 -0
- data/lib/carat/duckhunter.rb +158 -0
- data/lib/carat/dynamic-mixin.rb +71 -0
- data/lib/carat/enumerable-args.rb +125 -0
- data/lib/carat/expect.rb +192 -0
- data/lib/carat/filelist.rb +277 -0
- data/lib/carat/floatstring.rb +153 -0
- data/lib/carat/functor.rb +41 -0
- data/lib/carat/harray.rb +507 -0
- data/lib/carat/heap.rb +193 -0
- data/lib/carat/html-helpers.rb +82 -0
- data/lib/carat/infinity.rb +61 -0
- data/lib/carat/init.rb +33 -0
- data/lib/carat/interval.rb +248 -0
- data/lib/carat/io-reactor.rb +657 -0
- data/lib/carat/io-redirect.rb +99 -0
- data/lib/carat/lisp-format.rb +1832 -0
- data/lib/carat/lisp.rb +336 -0
- data/lib/carat/macro.rb +68 -0
- data/lib/carat/multiton.rb +153 -0
- data/lib/carat/nack.rb +115 -0
- data/lib/carat/nil-comparable.rb +67 -0
- data/lib/carat/nil-missing.rb +12 -0
- data/lib/carat/notcopyable.rb +68 -0
- data/lib/carat/orderedhash.rb +249 -0
- data/lib/carat/ostructable.rb +138 -0
- data/lib/carat/parser-old.rb +350 -0
- data/lib/carat/parser.rb +393 -0
- data/lib/carat/ref.rb +31 -0
- data/lib/carat/semaphore.rb +69 -0
- data/lib/carat/snapshot.rb +94 -0
- data/lib/carat/soundex.rb +104 -0
- data/lib/carat/sstruct.rb +223 -0
- data/lib/carat/statichash.rb +49 -0
- data/lib/carat/tagiter.rb +345 -0
- data/lib/carat/timelimit.rb +114 -0
- data/lib/carat/timer.rb +99 -0
- data/lib/carat/tracepoint.rb +154 -0
- data/lib/carat/tuple.rb +31 -0
- data/lib/carat/uninheritable.rb +68 -0
- data/lib/carat/version.rb +147 -0
- data/pub/doc/sstruct.txt +204 -0
- data/pub/doc/tagiter.html +145 -0
- data/setup.rb +1361 -0
- data/test/fixtures/filelist/testfile.txt +1 -0
- data/test/fixtures/filelist/testfile2.txt +1 -0
- data/test/tc_1st.rb +16 -0
- data/test/tc_ansicolor.rb +23 -0
- data/test/tc_attr.rb +46 -0
- data/test/tc_bbcode.rb +20 -0
- data/test/tc_binaryreader.rb +14 -0
- data/test/tc_binding_of_caller.rb +2 -0
- data/test/tc_byteorder.rb +41 -0
- data/test/tc_constant.rb +12 -0
- data/test/tc_coroutine.rb +50 -0
- data/test/tc_crosscase.rb +33 -0
- data/test/tc_duckhunter.rb +37 -0
- data/test/tc_dynamic-mixin.rb +66 -0
- data/test/tc_enumerable-args.rb +66 -0
- data/test/tc_expect.rb +83 -0
- data/test/tc_filelist.rb +17 -0
- data/test/tc_floatstring.rb +22 -0
- data/test/tc_functor.rb +18 -0
- data/test/tc_harray.rb +280 -0
- data/test/tc_heap.rb +6 -0
- data/test/tc_infinity.rb +23 -0
- data/test/tc_init.rb +29 -0
- data/test/tc_interval.rb +153 -0
- data/test/tc_io-reactor.rb +5 -0
- data/test/tc_io-redirect.rb +5 -0
- data/test/tc_lisp-format.rb +24 -0
- data/test/tc_lisp.rb +32 -0
- data/test/tc_macro.rb +48 -0
- data/test/tc_multiton.rb +188 -0
- data/test/tc_nack.rb +31 -0
- data/test/tc_nil-as-emptiness.rb +19 -0
- data/test/tc_nil-comparable.rb +29 -0
- data/test/tc_nil-missing.rb +0 -0
- data/test/tc_notcopyable.rb +64 -0
- data/test/tc_orderedhash.rb +36 -0
- data/test/tc_ostructable.rb +31 -0
- data/test/tc_semaphore.rb +5 -0
- data/test/tc_snapshot.rb +20 -0
- data/test/tc_soundex.rb +19 -0
- data/test/tc_sstruct.rb +313 -0
- data/test/tc_statichash.rb +24 -0
- data/test/tc_tagiter.rb +80 -0
- data/test/tc_timelimit.rb +47 -0
- data/test/tc_timer.rb +35 -0
- data/test/tc_tracepoint.rb +10 -0
- data/test/tc_tuple.rb +25 -0
- data/test/tc_uninheritable.rb +33 -0
- data/test/tc_version.rb +90 -0
- metadata +531 -0
data/ChangeLog
ADDED
data/LICENSE
ADDED
data/README
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
= Ruby Carats, the Ruby Toolchest
|
|
2
|
+
|
|
3
|
+
== Introduction
|
|
4
|
+
|
|
5
|
+
Ruby Carats is an extensive, 100% pure Ruby, general purposed library collection
|
|
6
|
+
of classes amd modules. It is an open repository for useful
|
|
7
|
+
general puroposed and well tested classes, modules, mixins.
|
|
8
|
+
|
|
9
|
+
== Installation
|
|
10
|
+
|
|
11
|
+
To do a manual install untar and use the included setup.rb script.
|
|
12
|
+
|
|
13
|
+
> tar -xvzf carats-x.y.z.tar.gz
|
|
14
|
+
> cd carats-x.y.z
|
|
15
|
+
> sudo ruby setup.rb
|
|
16
|
+
|
|
17
|
+
== Usage
|
|
18
|
+
|
|
19
|
+
Umm... that might require a book. You should look at the API docs.
|
|
20
|
+
To date, not everything in documented. But it's getting there.
|
|
21
|
+
You are welcome to help out. The basic require is:
|
|
22
|
+
|
|
23
|
+
require 'carat/<file>'
|
|
24
|
+
|
|
25
|
+
== Authorship
|
|
26
|
+
|
|
27
|
+
This collection was put together by, and largely written by Thomas Sawyer
|
|
28
|
+
(aka T. Onoma). He can be reached via email at transami at runbox.com.
|
|
29
|
+
|
|
30
|
+
This package is a collection of work by many persons.
|
|
31
|
+
If it matters, the collection per collection is licensed:
|
|
32
|
+
|
|
33
|
+
Ruby Carats
|
|
34
|
+
Copyright (c) 2004-2005 Thomas Sawyer
|
|
35
|
+
Ruby License
|
|
36
|
+
|
|
37
|
+
But the actual code on is licensed according to the original authors
|
|
38
|
+
desires, being one of the following: Ruby, GPL, LGPL, MIT, or Artistic.
|
|
39
|
+
Copies of these licenses should accompany this document. Any piece of code
|
|
40
|
+
not specifically laballed shall fall under the Ruby License.
|
|
41
|
+
|
|
42
|
+
[Please Note: I am working to make sure everything is labeled appropriately.
|
|
43
|
+
Please forgive me if I have not done so in a particular place --just let
|
|
44
|
+
me know and I will fix.]
|
|
45
|
+
|
|
46
|
+
Also, I would like to ask all those authors, whose code is collected here,
|
|
47
|
+
to consider moving to the Ruby license, so one license can serve for all.
|
|
48
|
+
|
|
49
|
+
=== Attributed Authors
|
|
50
|
+
|
|
51
|
+
* Thomas Sawyer
|
|
52
|
+
* Paul Brannan
|
|
53
|
+
* Renald Buter
|
|
54
|
+
* Hal Fulton
|
|
55
|
+
* Gavin Sinclair
|
|
56
|
+
* Michael Granger
|
|
57
|
+
* Michael Neumann
|
|
58
|
+
* Florian Frank
|
|
59
|
+
* Mohammad Khan
|
|
60
|
+
* Derek Lewis
|
|
61
|
+
* Thomas-Ivo Heinen
|
|
62
|
+
* Jan Molic
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
== Pitch
|
|
66
|
+
|
|
67
|
+
ALL YOUR BASE ARE BELONG TO RUBY
|
data/Reapfile
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
--- %YAML:1.0
|
|
2
|
+
|
|
3
|
+
TITLE: &title Ruby Carats
|
|
4
|
+
NAME: &pkg carats
|
|
5
|
+
VERSION: '0.3.0'
|
|
6
|
+
AUTHOR: Trans Onoma
|
|
7
|
+
EMAIL: transfire@gmail.com
|
|
8
|
+
HOMEPAGE: "http://calibre.rubyforge.org"
|
|
9
|
+
|
|
10
|
+
SUMMARY: Collection of classes, modules, and mixins.
|
|
11
|
+
|
|
12
|
+
DESCRIPTION: >
|
|
13
|
+
Ruby Carats is a large collection of additions for
|
|
14
|
+
the Ruby programming language. Carats is broard in it
|
|
15
|
+
coverage and draws heavily on many works by many
|
|
16
|
+
authors. Ruby Carats is a subproject of Ruby Calibre.
|
|
17
|
+
|
|
18
|
+
RUBYFORGE:
|
|
19
|
+
PROJECT: 'calibre'
|
|
20
|
+
USERNAME: transami
|
|
21
|
+
|
|
22
|
+
TEST:
|
|
23
|
+
FILES:
|
|
24
|
+
- 'test/**/tc_*.rb'
|
|
25
|
+
OPTIONS: ~
|
|
26
|
+
|
|
27
|
+
RDOC:
|
|
28
|
+
TITLE: *title
|
|
29
|
+
DIR: 'doc'
|
|
30
|
+
TEMPLATE: html #ruby-red
|
|
31
|
+
OPTIONS: ['--merge', '--inline-source', --'all']
|
|
32
|
+
MAIN: README
|
|
33
|
+
INCLUDE:
|
|
34
|
+
- 'README'
|
|
35
|
+
- 'LICEN*'
|
|
36
|
+
- 'lib/carat/**/*.rb'
|
|
37
|
+
EXCLUDE: []
|
|
38
|
+
|
|
39
|
+
PACKAGE:
|
|
40
|
+
DIR: pkg
|
|
41
|
+
INCLUDE:
|
|
42
|
+
- 'lib/**/*'
|
|
43
|
+
- 'bench/**/*'
|
|
44
|
+
- 'test/**/*'
|
|
45
|
+
- 'rdoc/**/*'
|
|
46
|
+
- 'doc/**/*'
|
|
47
|
+
- 'pub/**/*'
|
|
48
|
+
- 'demo/**/*'
|
|
49
|
+
- 'samples/**/*'
|
|
50
|
+
- 'examples/**/*'
|
|
51
|
+
- 'setup.rb'
|
|
52
|
+
- '[A-Z]*'
|
|
53
|
+
EXCLUDE:
|
|
54
|
+
- InstalledFiles
|
|
55
|
+
ZIP: true
|
|
56
|
+
GZIP: true
|
|
57
|
+
BZIP2: true
|
|
58
|
+
GEM: true
|
|
59
|
+
|
|
60
|
+
ANNOUNCE:
|
|
61
|
+
TO: tranfire@gmail.com
|
|
62
|
+
FROM: transfire@gmail.com
|
|
63
|
+
DOMAIN: jupiterzeus.net
|
|
64
|
+
SERVER: gmail.com
|
|
65
|
+
PORT: 25
|
|
66
|
+
ACCOUNT: transfire@gmail.com
|
|
67
|
+
AUTHTYPE: plain #cram_md5
|
|
68
|
+
FILE: ANN
|
|
69
|
+
SLOGAN: ALL YOUR BASE ARE BELONG TO RUBY!
|
|
70
|
+
INFO:
|
|
71
|
+
- http://calibre.rubyforge.org
|
|
72
|
+
|
data/ToDo
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
- Minor:
|
|
3
|
+
- ordered-hash, would like an improved version.
|
|
4
|
+
- nil-comparable, works but I think could done better.
|
|
5
|
+
- lisp, there may be other places where #pair! is needed.
|
|
6
|
+
- interval, add infinity as possible sentinal.
|
|
7
|
+
- duckhunter (might be able to use Functor as decoy/probe)
|
|
8
|
+
|
|
9
|
+
- Carat-dev:
|
|
10
|
+
- interface
|
|
11
|
+
- detach
|
|
12
|
+
|
|
13
|
+
- Tests:
|
|
14
|
+
- binaryreader
|
|
15
|
+
- binding_of_caller
|
|
16
|
+
- coroutine, currently just checks for no error raised
|
|
17
|
+
- heap
|
|
18
|
+
- io-reactor
|
|
19
|
+
- io-redirect
|
|
20
|
+
- semaphore
|
|
21
|
+
- tracepoint
|
|
22
|
+
- 1st, needs some sort of refinement
|
|
23
|
+
- lisp, needs to be vastly expanded
|
|
24
|
+
- lisp_format, code use a few more tests
|
data/bench/b_harray.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
|
|
3
|
+
Some speed comparisions between standard Array and HArray.
|
|
4
|
+
|
|
5
|
+
=end
|
|
6
|
+
|
|
7
|
+
require 'trix/harray'
|
|
8
|
+
require 'benchmark'
|
|
9
|
+
|
|
10
|
+
$n = 50000
|
|
11
|
+
|
|
12
|
+
# standard array
|
|
13
|
+
|
|
14
|
+
def sarray_make
|
|
15
|
+
$n.times do
|
|
16
|
+
$sa = [1,'a',nil]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def sarray_slice
|
|
21
|
+
$n.times do
|
|
22
|
+
$sa[1..2]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# hash array
|
|
27
|
+
|
|
28
|
+
def harray_make
|
|
29
|
+
$n.times do
|
|
30
|
+
$ha = HArray.new_h({0=>1,1=>'a',2=>nil})
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def harray_slice
|
|
35
|
+
$n.times do
|
|
36
|
+
$ha[1..2]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### --- bench ---
|
|
42
|
+
|
|
43
|
+
puts "\nCURRENT"
|
|
44
|
+
Benchmark.bm(15) do |b|
|
|
45
|
+
b.report("HAarry#new:") { harray_make }
|
|
46
|
+
b.report("HArray#slice:") { harray_slice }
|
|
47
|
+
b.report("Array#new:") { sarray_make }
|
|
48
|
+
b.report("Array#slice:") { sarray_slice }
|
|
49
|
+
end
|
data/bench/b_range.rb
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
|
|
2
|
+
require 'benchmark'
|
|
3
|
+
|
|
4
|
+
# member?
|
|
5
|
+
|
|
6
|
+
$n = 50000
|
|
7
|
+
|
|
8
|
+
def range_nan
|
|
9
|
+
$n.times { ('a'..'k').member?('f') }
|
|
10
|
+
$n.times { ('a'..'k').member?('r') }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def range_small
|
|
14
|
+
$n.times { (0..6).member?(3) }
|
|
15
|
+
$n.times { (0..6).member?(7) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def range_med
|
|
19
|
+
$n.times { (0..1000).member?(500) }
|
|
20
|
+
$n.times { (0..1000).member?(1001) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# index
|
|
24
|
+
|
|
25
|
+
$a = [ 'x' ] * 100
|
|
26
|
+
$m = 500000
|
|
27
|
+
|
|
28
|
+
def range_index
|
|
29
|
+
i = 1
|
|
30
|
+
$m.times { $a[1..i]; i += 1 }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def length_index
|
|
34
|
+
i = 1
|
|
35
|
+
$m.times { $a[1,i]; i += 1 }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
### --- bench ---
|
|
39
|
+
|
|
40
|
+
puts "\nINDEXING"
|
|
41
|
+
Benchmark.bm(15) do |b|
|
|
42
|
+
b.report("range_index:") { range_index }
|
|
43
|
+
b.report("length_index:") { length_index }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
puts "\n\nNew vs. Old\n"
|
|
47
|
+
|
|
48
|
+
puts "\nCURRENT"
|
|
49
|
+
Benchmark.bm(15) do |b|
|
|
50
|
+
b.report("range_nan:") { range_nan }
|
|
51
|
+
b.report("range_samll:") { range_small }
|
|
52
|
+
b.report("range_med:") { range_med }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
puts "\nNEW"
|
|
56
|
+
require 'trix-dev/range/range'
|
|
57
|
+
Benchmark.bm(15) do |b|
|
|
58
|
+
b.report("range_nan:") { range_nan }
|
|
59
|
+
b.report("range_samll:") { range_small }
|
|
60
|
+
b.report("range_med:") { range_med }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
puts
|
|
64
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
## Little unix filter that colorizes diff output
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'term/ansicolor'
|
|
7
|
+
|
|
8
|
+
include Term::ANSIColor
|
|
9
|
+
|
|
10
|
+
ARGF.each do |line|
|
|
11
|
+
print(
|
|
12
|
+
case line
|
|
13
|
+
when /^\+/ then green { line }
|
|
14
|
+
when /^-/ then red { line }
|
|
15
|
+
when /^(@@|diff)/ then blue { line }
|
|
16
|
+
else line
|
|
17
|
+
end
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
# vim: set et sw=2 ts=2:
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'term/ansicolor'
|
|
2
|
+
|
|
3
|
+
# Use this trick to work around namespace cluttering that
|
|
4
|
+
# happens if you just include Term::ANSIColor:
|
|
5
|
+
|
|
6
|
+
class Color
|
|
7
|
+
class << self
|
|
8
|
+
include Term::ANSIColor
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
print Color.red, Color.bold, "No Namespace cluttering:", Color.clear, "\n"
|
|
13
|
+
print Color.green + "green" + Color.clear, "\n"
|
|
14
|
+
print Color.on_red(Color.green("green")), "\n"
|
|
15
|
+
print Color.yellow { Color.on_black { "yellow on_black" } }, "\n\n"
|
|
16
|
+
|
|
17
|
+
# Anyway, I don't define any of Term::ANSIColor's methods in this example
|
|
18
|
+
# and I want to keep it short:
|
|
19
|
+
include Term::ANSIColor
|
|
20
|
+
|
|
21
|
+
print red, bold, "Usage as constants:", reset, "\n"
|
|
22
|
+
print clear, "clear", reset, reset, "reset", reset,
|
|
23
|
+
bold, "bold", reset, dark, "dark", reset,
|
|
24
|
+
underscore, "underscore", reset, blink, "blink", reset,
|
|
25
|
+
negative, "negative", reset, concealed, "concealed", reset, "|\n",
|
|
26
|
+
black, "black", reset, red, "red", reset, green, "green", reset,
|
|
27
|
+
yellow, "yellow", reset, blue, "blue", reset, magenta, "magenta", reset,
|
|
28
|
+
cyan, "cyan", reset, white, "white", reset, "|\n",
|
|
29
|
+
on_black, "on_black", reset, on_red, "on_red", reset,
|
|
30
|
+
on_green, "on_green", reset, on_yellow, "on_yellow", reset,
|
|
31
|
+
on_blue, "on_blue", reset, on_magenta, "on_magenta", reset,
|
|
32
|
+
on_cyan, "on_cyan", reset, on_white, "on_white", reset, "|\n\n"
|
|
33
|
+
|
|
34
|
+
print red, bold, "Usage as unary functions:", reset, "\n"
|
|
35
|
+
print clear("clear"), reset("reset"), bold("bold"), dark("dark"),
|
|
36
|
+
underscore("underscore"), blink("blink"), negative("negative"),
|
|
37
|
+
concealed("concealed"), "|\n",
|
|
38
|
+
black("black"), red("red"), green("green"), yellow("yellow"),
|
|
39
|
+
blue("blue"), magenta("magenta"), cyan("cyan"), white("white"), "|\n",
|
|
40
|
+
on_black("on_black"), on_red("on_red"), on_green("on_green"),#
|
|
41
|
+
on_yellow("on_yellow"), on_blue("on_blue"), on_magenta("on_magenta"),
|
|
42
|
+
on_cyan("on_cyan"), on_white("on_white"), "|\n\n"
|
|
43
|
+
|
|
44
|
+
print red { bold { "Usage as block forms:" } }, "\n"
|
|
45
|
+
print clear { "clear" }, reset { "reset" }, bold { "bold" },
|
|
46
|
+
dark { "dark" }, underscore { "underscore" }, blink { "blink" },
|
|
47
|
+
negative { "negative" }, concealed { "concealed" }, "|\n",
|
|
48
|
+
black { "black" }, red { "red" }, green { "green" },
|
|
49
|
+
yellow { "yellow" }, blue { "blue" }, magenta { "magenta" },
|
|
50
|
+
cyan { "cyan" }, white { "white" }, "|\n",
|
|
51
|
+
on_black { "on_black" }, on_red { "on_red" }, on_green { "on_green" },
|
|
52
|
+
on_yellow { "on_yellow" }, on_blue { "on_blue" },
|
|
53
|
+
on_magenta { "on_magenta" }, on_cyan { "on_cyan" },
|
|
54
|
+
on_white { "on_white" }, "|\n\n"
|
|
55
|
+
|
|
56
|
+
# Usage as Mixin into String or its Subclasses
|
|
57
|
+
class String
|
|
58
|
+
include Term::ANSIColor
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
print "Usage as String Mixins:".red.bold, "\n"
|
|
62
|
+
print "clear".clear, "reset".reset, "bold".bold, "dark".dark,
|
|
63
|
+
"underscore".underscore, "blink".blink, "negative".negative,
|
|
64
|
+
"concealed".concealed, "|\n",
|
|
65
|
+
"black".black, "red".red, "green".green, "yellow".yellow,
|
|
66
|
+
"blue".blue, "magenta".magenta, "cyan".cyan, "white".white, "|\n",
|
|
67
|
+
"on_black".on_black, "on_red".on_red, "on_green".on_green,
|
|
68
|
+
"on_yellow".on_yellow, "on_blue".on_blue, "on_magenta".on_magenta,
|
|
69
|
+
"on_cyan".on_cyan, "on_white".on_white, "|\n\n"
|
|
70
|
+
|
|
71
|
+
symbols = Term::ANSIColor::attributes
|
|
72
|
+
print red { bold { "All supported attributes = " } },
|
|
73
|
+
blue { symbols.inspect }, "\n\n"
|
|
74
|
+
|
|
75
|
+
print "Send symbols to strings:".send(:red).send(:bold), "\n"
|
|
76
|
+
print symbols[12, 8].map { |c| c.to_s.send(c) }, "\n\n"
|
|
77
|
+
|
|
78
|
+
print red { bold { "Make strings monochromatic again:" } }, "\n"
|
|
79
|
+
print [ "red".red, "not red anymore".red.uncolored,
|
|
80
|
+
uncolored { "not red anymore".red }, uncolored("not red anymore".red)
|
|
81
|
+
].map { |x| x + "\n" }
|
|
82
|
+
# vim: set et sw=2 ts=2:
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
# = chatserver.rb
|
|
3
|
+
#
|
|
4
|
+
# This is an extremely crude and simple single-threaded multiplexing chat
|
|
5
|
+
# server. It (hopefully) demonstrates how to use a IO::Reactor object to do IO
|
|
6
|
+
# multiplexing with events.
|
|
7
|
+
#
|
|
8
|
+
# == Synopsis
|
|
9
|
+
#
|
|
10
|
+
# $ chatserver.rb [HOST [PORT [LOOPTIMEOUT]]]
|
|
11
|
+
#
|
|
12
|
+
# [HOST]
|
|
13
|
+
# The host or IP the server will bind to
|
|
14
|
+
#
|
|
15
|
+
# [PORT]
|
|
16
|
+
# The port the server will listen on
|
|
17
|
+
#
|
|
18
|
+
# [LOOPTIMEOUT]
|
|
19
|
+
# The number of floating-point seconds between polls. Specifying -1 (or any
|
|
20
|
+
# negative number, really) here will make the server's event loop block on the
|
|
21
|
+
# call to #poll.
|
|
22
|
+
#
|
|
23
|
+
# == Author
|
|
24
|
+
#
|
|
25
|
+
# Michael Granger <ged@FaerieMUD.org>
|
|
26
|
+
#
|
|
27
|
+
# Copyright (c) 2002, 2003 The FaerieMUD Consortium. All rights reserved.
|
|
28
|
+
#
|
|
29
|
+
# This program is free software. You may use, modify, and/or redistribute this
|
|
30
|
+
# software under the same terms as Ruby itself.
|
|
31
|
+
#
|
|
32
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
33
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
34
|
+
# FOR A PARTICULAR PURPOSE.
|
|
35
|
+
#
|
|
36
|
+
# == Version
|
|
37
|
+
#
|
|
38
|
+
# $Id: chatserver.rb,v 1.4 2003/08/04 23:53:32 deveiant Exp $
|
|
39
|
+
#
|
|
40
|
+
|
|
41
|
+
require 'io/reactor'
|
|
42
|
+
require 'socket'
|
|
43
|
+
|
|
44
|
+
module Example
|
|
45
|
+
|
|
46
|
+
### Chatserver user class -- part of the chatserver example.
|
|
47
|
+
class User
|
|
48
|
+
|
|
49
|
+
MTU = 4096
|
|
50
|
+
CR = "\015"
|
|
51
|
+
LF = "\012"
|
|
52
|
+
EOL = CR + LF
|
|
53
|
+
|
|
54
|
+
PROMPT = 'chat> '
|
|
55
|
+
|
|
56
|
+
### Create and return a user object which will use the specified
|
|
57
|
+
### <tt>socket</tt> and <tt>pollObj</tt>.
|
|
58
|
+
def initialize( socket, server )
|
|
59
|
+
@socket = socket
|
|
60
|
+
@server = server
|
|
61
|
+
@obuffer = ''
|
|
62
|
+
@ibuffer = ''
|
|
63
|
+
@peerHost = @socket.peeraddr[2]
|
|
64
|
+
@peerPort = @socket.peeraddr[1]
|
|
65
|
+
@connected = true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Object attribute
|
|
69
|
+
attr_reader :socket, :server, :ibuffer, :obuffer
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
### Return a stringified version of the user
|
|
73
|
+
def to_s
|
|
74
|
+
"%s:%d" % [ @peerHost, @peerPort ]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
### Add the specified string to the user's output buffer and turn on
|
|
79
|
+
### output events.
|
|
80
|
+
def addOutput( string )
|
|
81
|
+
@obuffer << string.chomp << EOL
|
|
82
|
+
@server.reactor.enableEvents( @socket, :write )
|
|
83
|
+
end
|
|
84
|
+
alias :<< :addOutput
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### Write as much of the output buffer to the socket as possible, and return
|
|
88
|
+
### the number of bytes remaining to be sent.
|
|
89
|
+
def writeOutput
|
|
90
|
+
bytes = @socket.syswrite( @obuffer )
|
|
91
|
+
@obuffer[ 0, bytes ] = '' if bytes.nonzero?
|
|
92
|
+
return @obuffer.length
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
### Write a prompt to the user
|
|
97
|
+
def prompt
|
|
98
|
+
@obuffer << PROMPT
|
|
99
|
+
@server.reactor.enableEvents( @socket, :write )
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
### Read at most MTU bytes from the socket and append them to the input
|
|
104
|
+
### buffer. Split off any complete lines (one that end with EOL) and return
|
|
105
|
+
### them as an Array of Strings.
|
|
106
|
+
def readInput
|
|
107
|
+
rary = []
|
|
108
|
+
@ibuffer << @socket.sysread( MTU )
|
|
109
|
+
$stderr.puts "Input buffer for user #{self} now: #@ibuffer" if $VERBOSE
|
|
110
|
+
while (( pos = @ibuffer.index EOL ))
|
|
111
|
+
$stderr.puts "Found terminating EOL. "\
|
|
112
|
+
"Splitting off 0..#{pos} of the input buffer." if $VERBOSE
|
|
113
|
+
rary << @ibuffer[ 0, pos ]
|
|
114
|
+
@ibuffer[ 0, pos + EOL.length ] = ''
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
return rary
|
|
118
|
+
rescue EOFError
|
|
119
|
+
@server.disconnectUser( self )
|
|
120
|
+
return []
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
### Handle poll events on the socket
|
|
125
|
+
def handleIOEvent( io, event )
|
|
126
|
+
case event
|
|
127
|
+
|
|
128
|
+
when :error
|
|
129
|
+
@server.disconnectUser( self )
|
|
130
|
+
|
|
131
|
+
when :read
|
|
132
|
+
input = readInput()
|
|
133
|
+
@server.processInput( self, *input ) unless input.empty?
|
|
134
|
+
|
|
135
|
+
when :write
|
|
136
|
+
bytesLeft = writeOutput()
|
|
137
|
+
@server.reactor.disableEvents( @socket, :write ) if bytesLeft.zero?
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
### Disconnect the user
|
|
145
|
+
def disconnect( msg='' )
|
|
146
|
+
@connected = false
|
|
147
|
+
unless msg.empty?
|
|
148
|
+
@obuffer = ">>> Disconnected: #{msg} <<<" + EOL
|
|
149
|
+
else
|
|
150
|
+
@obuffer = ">>> Disconnected <<<" + EOL
|
|
151
|
+
end
|
|
152
|
+
writeOutput()
|
|
153
|
+
@socket.close
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
### Returns true if the user is still connected
|
|
158
|
+
def connected?
|
|
159
|
+
@connected
|
|
160
|
+
end
|
|
161
|
+
end # class User
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
### Example chatserver class -- an extremely crude and simple chat server that
|
|
165
|
+
### demonstrates how to use Poll to do multiplexing IO in a single thread.
|
|
166
|
+
class Server
|
|
167
|
+
|
|
168
|
+
BANNER = <<-EOF
|
|
169
|
+
[[ IO::Reactor Example Chatserver ]]
|
|
170
|
+
Commands: '/quit' to quit, '/shutdown' to shut the server down
|
|
171
|
+
EOF
|
|
172
|
+
|
|
173
|
+
### Instantiate and return a chatserver on the specified host and port
|
|
174
|
+
def initialize( listenHost="0.0.0.0", listenPort=1138, interval=0.20 )
|
|
175
|
+
@socket = TCPServer::new( listenHost, listenPort )
|
|
176
|
+
@users = []
|
|
177
|
+
@reactor = IO::Reactor::new
|
|
178
|
+
@pollInterval = interval
|
|
179
|
+
@shuttingDown = false
|
|
180
|
+
|
|
181
|
+
@reactor.register @socket, :read, &method(:handlePollEvent)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Server attributes
|
|
185
|
+
attr_reader :reactor, :users, :socket
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
### Main server loop
|
|
189
|
+
def eventLoop
|
|
190
|
+
trap( "INT" ) { shutdown("Server caught SIGINT") }
|
|
191
|
+
trap( "TERM" ) { shutdown("Server caught SIGTERM") }
|
|
192
|
+
trap( "HUP" ) { disconnectAllUsers(">>> Server reset <<<") }
|
|
193
|
+
|
|
194
|
+
until @shuttingDown
|
|
195
|
+
eventCount = @reactor.poll( @pollInterval )
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
rescue StandardError => e
|
|
199
|
+
$stderr.puts "Error in server: #{e.message}"
|
|
200
|
+
$stderr.puts "\t" + e.backtrace.join( "\n\t" )
|
|
201
|
+
shutdown( "Server error: #{e.message}" )
|
|
202
|
+
rescue SignalException => e
|
|
203
|
+
shutdown( "Server caught #{e.type.name}" )
|
|
204
|
+
ensure
|
|
205
|
+
trap( "INT", "SIG_IGN" )
|
|
206
|
+
trap( "TERM", "SIG_IGN" )
|
|
207
|
+
trap( "HUP", "SIG_IGN" )
|
|
208
|
+
|
|
209
|
+
$stderr.puts "Server exiting event loop."
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
### Handle a poll event specified by <tt>event</tt> on the specified
|
|
214
|
+
### <tt>socket</tt>
|
|
215
|
+
def handlePollEvent( socket, event )
|
|
216
|
+
$stderr.puts "Got #{event.inspect} event for #{socket.inspect}"
|
|
217
|
+
|
|
218
|
+
case event
|
|
219
|
+
when :error
|
|
220
|
+
$stderr.puts "Socket error on the listener socket."
|
|
221
|
+
shutdown()
|
|
222
|
+
|
|
223
|
+
when :read
|
|
224
|
+
clSock = socket.accept
|
|
225
|
+
user = User::new( clSock, self )
|
|
226
|
+
$stderr.puts "Accepted connection from #{user}"
|
|
227
|
+
@reactor.register clSock, :read, &user.method(:handleIOEvent)
|
|
228
|
+
user.addOutput( BANNER )
|
|
229
|
+
user.prompt
|
|
230
|
+
broadcastMsg( "[New connection: #{user}]" )
|
|
231
|
+
@users << user
|
|
232
|
+
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
### Process the specified input from the specified user
|
|
238
|
+
def processInput( user, *inputStrings )
|
|
239
|
+
inputStrings.each {|str|
|
|
240
|
+
case str
|
|
241
|
+
|
|
242
|
+
when %r{^/(\w+)\s*(.*)}
|
|
243
|
+
handleCommand( user, $1, $2 )
|
|
244
|
+
|
|
245
|
+
else
|
|
246
|
+
user.addOutput( "You>> #{str}" )
|
|
247
|
+
broadcastMsgFrom( user, str )
|
|
248
|
+
end
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
user.prompt if user.connected?
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
### Handle the specified command from the specified user
|
|
256
|
+
def handleCommand( user, command, args )
|
|
257
|
+
case command
|
|
258
|
+
|
|
259
|
+
when /quit/
|
|
260
|
+
disconnectUser( user, 'Quit' )
|
|
261
|
+
|
|
262
|
+
when /shutdown/
|
|
263
|
+
shutdown()
|
|
264
|
+
|
|
265
|
+
when /who/
|
|
266
|
+
user.addOutput( self.wholist(user) )
|
|
267
|
+
|
|
268
|
+
else
|
|
269
|
+
user.addOutput("Unknown command '#{command}'")
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
### Broadcast the specified message to all connected users
|
|
275
|
+
def broadcastMsg( msg )
|
|
276
|
+
@users.each {|cl|
|
|
277
|
+
cl.addOutput( msg )
|
|
278
|
+
}
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
### Broadcast the specified message from the specified user
|
|
283
|
+
def broadcastMsgFrom( user, msg )
|
|
284
|
+
userDesc = user.to_s
|
|
285
|
+
|
|
286
|
+
@users.each {|cl|
|
|
287
|
+
next if cl == user
|
|
288
|
+
cl.addOutput( "#{userDesc}>> #{msg}" )
|
|
289
|
+
}
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
### Disconnect the specified user
|
|
294
|
+
def disconnectUser( user, msg='' )
|
|
295
|
+
@users -= [ user ]
|
|
296
|
+
@reactor.unregister( user.socket )
|
|
297
|
+
user.disconnect( msg )
|
|
298
|
+
broadcastMsg( "#{user.to_s} Disconnected." )
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
### Disconnect all connected users
|
|
303
|
+
def disconnectAllUsers( msg )
|
|
304
|
+
@users.each {|user|
|
|
305
|
+
@reactor.unregister( user.socket )
|
|
306
|
+
user.disconnect( msg )
|
|
307
|
+
}
|
|
308
|
+
@users.clear
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
### Shut the server down
|
|
313
|
+
def shutdown( msg="Server shutdown" )
|
|
314
|
+
$stderr.puts "Shutting down: #{msg}"
|
|
315
|
+
@shuttingDown = true
|
|
316
|
+
@reactor.clear
|
|
317
|
+
begin
|
|
318
|
+
@socket.shutdown
|
|
319
|
+
rescue
|
|
320
|
+
end
|
|
321
|
+
disconnectAllUsers( msg )
|
|
322
|
+
begin
|
|
323
|
+
@socket.close
|
|
324
|
+
rescue
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
### Build and return a list of connected users for the specified user.
|
|
329
|
+
def wholist( user )
|
|
330
|
+
rval = "[Connected Users]\n" <<
|
|
331
|
+
" *#{user}*\n"
|
|
332
|
+
@users.each {|u|
|
|
333
|
+
next if u == user
|
|
334
|
+
rval << " #{u}\n"
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return rval
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
end # class Server
|
|
341
|
+
end # module Example
|
|
342
|
+
|
|
343
|
+
srv = Example::Server::new( *ARGV )
|
|
344
|
+
$stderr.puts "Chat server listening on #{srv.socket.addr[2]} port #{srv.socket.addr[1]}"
|
|
345
|
+
srv.eventLoop
|
|
346
|
+
$stderr.puts "Chat server finished."
|
|
347
|
+
|