walnut 0.0.1 → 0.1.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/Gemfile +2 -1
- data/README.md +4 -1
- data/Rakefile +40 -1
- data/docs/interfaces/Input.md +4 -4
- data/docs/interfaces/Output.md +19 -0
- data/lib/walnut.rb +15 -0
- data/lib/walnut/{config.rb → configuration.rb} +31 -0
- data/lib/walnut/events.rb +85 -0
- data/lib/walnut/input/readline.rb +49 -0
- data/lib/walnut/output/standard.rb +47 -0
- data/lib/walnut/shell.rb +71 -2
- data/lib/walnut/version.rb +1 -1
- data/sample/echo.rb +28 -0
- data/sample/repl.rb +63 -0
- data/spec/events_spec.rb +55 -0
- data/spec/helper.rb +7 -0
- data/spec/input_spec.rb +46 -0
- data/spec/output_spec.rb +41 -0
- data/walnut.gemspec +2 -2
- metadata +19 -5
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
walnut
|
2
2
|
======
|
3
3
|
|
4
|
-
|
4
|
+
[](https://travis-ci.org/noxgirl/walnut)
|
5
|
+
|
6
|
+
_The crunchy shell building framework!_
|
5
7
|
|
6
8
|
+ [Homepage](http://git.io/walnutrb)
|
7
9
|
+ [Documentation](http://rdoc.info/github/noxgirl/walnut/)
|
10
|
+
+ [RubyGems](https://rubygems.org/gems/walnut)
|
8
11
|
|
9
12
|
**_Please see_** the licensing terms in LICENSE.md. walnut is free, open-source
|
10
13
|
software distributed under the permissive terms of the **MIT license**.
|
data/Rakefile
CHANGED
@@ -2,6 +2,45 @@
|
|
2
2
|
# All rights reserved.
|
3
3
|
# Distributed under the terms of the MIT license (see LICENSE.md).
|
4
4
|
|
5
|
-
|
5
|
+
task :default => [:testing]
|
6
|
+
task :gem => [:default, :make_gem, :release_gem]
|
7
|
+
|
8
|
+
# Turn off echoing
|
9
|
+
verbose false
|
10
|
+
|
11
|
+
desc 'Test the application.'
|
12
|
+
task :testing do
|
13
|
+
inc = "-i lib"
|
14
|
+
tests = [ File.join(%w[ spec *spec.rb ]) ]
|
15
|
+
|
16
|
+
tests.each do |t|
|
17
|
+
sh "bacon #{inc} #{t}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Create a gem from the gemspec.'
|
22
|
+
task :make_gem do
|
23
|
+
sh "gem build #{Dir["*.gemspec"].first}"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Install the gem.'
|
27
|
+
task :install => :make_gem do
|
28
|
+
sh "gem install #{Dir["*.gem"].last}"
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Push this release to RubyGems.'
|
32
|
+
task :release_gem => :make_gem do
|
33
|
+
sh "gem push #{Dir["*.gem"].last}"
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'Run a sample'
|
37
|
+
task :sample, :name do |t, args|
|
38
|
+
args.with_defaults(:name => nil)
|
39
|
+
if args[:name].nil?
|
40
|
+
puts Dir["sample/*.rb"].map {|x| x.chomp(".rb").sub(/sample\//, '').prepend "- " }
|
41
|
+
else
|
42
|
+
sh "ruby -I lib/ sample/#{args[:name]}.rb"
|
43
|
+
end
|
44
|
+
end
|
6
45
|
|
7
46
|
# vim: set ts=4 sts=2 sw=2 et:
|
data/docs/interfaces/Input.md
CHANGED
@@ -6,19 +6,19 @@ Synopsis
|
|
6
6
|
|
7
7
|
Input drivers require elements which any IO object would generally mandate.
|
8
8
|
|
9
|
-
The essential ability to read,
|
9
|
+
The essential ability to read, and to test for an end of input.
|
10
10
|
|
11
11
|
Methods
|
12
12
|
-------
|
13
13
|
|
14
14
|
A basic input driver will require the following as a bare minimum:
|
15
15
|
|
16
|
-
- read(
|
17
|
-
- write(\*strings) -- Write to the input.
|
16
|
+
- read() -- An alias for gets.
|
18
17
|
- eof?() -- Check for a closed stream.
|
19
|
-
- puts(\*strings) -- Write with appended newlines.
|
20
18
|
- gets() -- Read one line from the source.
|
21
19
|
- close() -- Close the stream.
|
22
20
|
|
23
21
|
Driver Implementations
|
24
22
|
----------------------
|
23
|
+
|
24
|
+
- Walnut::Input::Readline
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Interface for Walnut Input Drivers
|
2
|
+
==================================
|
3
|
+
|
4
|
+
Synopsis
|
5
|
+
--------
|
6
|
+
|
7
|
+
The essential ability to write is the only requirement for an Output object.
|
8
|
+
|
9
|
+
Methods
|
10
|
+
-------
|
11
|
+
|
12
|
+
A basic input driver will require the following as a bare minimum:
|
13
|
+
|
14
|
+
- write(string) -- Write (string) to the output stream.
|
15
|
+
- puts(string) -- Write (string) to the output stream with an appended newline character.
|
16
|
+
|
17
|
+
Driver Implementations
|
18
|
+
----------------------
|
19
|
+
|
data/lib/walnut.rb
CHANGED
@@ -4,6 +4,21 @@
|
|
4
4
|
|
5
5
|
require 'walnut/version'
|
6
6
|
require 'walnut/configuration'
|
7
|
+
require 'walnut/events'
|
7
8
|
require 'walnut/shell'
|
8
9
|
|
10
|
+
module Walnut
|
11
|
+
def self.configure
|
12
|
+
yield Walnut.config if block_given?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Set the default configuration
|
17
|
+
Walnut.configure do |c|
|
18
|
+
c.input = Walnut::Configuration.new
|
19
|
+
c.input.prompt = ">> "
|
20
|
+
c.input.history = []
|
21
|
+
|
22
|
+
c.output = Walnut::Configuration.new
|
23
|
+
end
|
9
24
|
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -1,12 +1,35 @@
|
|
1
1
|
# Copyright (c) 2013, Autumn Perrault, Matthew Carey
|
2
2
|
# All rights reserved.
|
3
3
|
# Distributed under the terms of the MIT license (see LICENSE.md).
|
4
|
+
require "ostruct"
|
4
5
|
|
5
6
|
module Walnut
|
6
7
|
|
7
8
|
# Dummy class to give a namespace to the configuration object.
|
8
9
|
class Configuration < OpenStruct
|
9
10
|
# Let's just do this to ensure that this has its own class
|
11
|
+
|
12
|
+
# Convenience for accessing keys
|
13
|
+
#
|
14
|
+
# @param [#to_s] key The key you are accessing
|
15
|
+
#
|
16
|
+
# @return [Object] The value of the key.
|
17
|
+
#
|
18
|
+
def [](key)
|
19
|
+
send(key.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Convenience method to set keys
|
23
|
+
#
|
24
|
+
# @param [#to_s] key The key you will be assigning the value to.
|
25
|
+
# @param [Object] value The new value to assign to the key.
|
26
|
+
#
|
27
|
+
# @return [Object] The value you passed to assign to the key.
|
28
|
+
#
|
29
|
+
def []=(key, value)
|
30
|
+
send(key.to_s << "=", value)
|
31
|
+
end
|
32
|
+
|
10
33
|
end
|
11
34
|
|
12
35
|
# Make a globally accessible configuration that general configuration will go
|
@@ -25,6 +48,14 @@ module Walnut
|
|
25
48
|
@walnut_global_configuration||=Configuration.new
|
26
49
|
end
|
27
50
|
|
51
|
+
def self.[](key)
|
52
|
+
self.config.send(key)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.[]=(key, value)
|
56
|
+
self.config.send(key.to_s << "=", value)
|
57
|
+
end
|
58
|
+
|
28
59
|
end
|
29
60
|
|
30
61
|
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, Matthew Carey
|
2
|
+
# All rights reserved.
|
3
|
+
# Distributed under the terms of the MIT license (see LICENSE.md).
|
4
|
+
|
5
|
+
module Walnut
|
6
|
+
|
7
|
+
# Setup events in Walnut as {Walnut.ev}.
|
8
|
+
def self.ev
|
9
|
+
@walnut_events ||= Walnut::Events.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# The simple yet fundamental events system of walnut.
|
13
|
+
#
|
14
|
+
# @author noxgirl
|
15
|
+
#
|
16
|
+
# @!attribute [r] events
|
17
|
+
# @return [Hash{String => Array<Array(Symbol, Proc)>}] The list of events.
|
18
|
+
#
|
19
|
+
# @!attribute [r] threads
|
20
|
+
# @return [Hash{String => Array<Thread>}] A list of threads.
|
21
|
+
class Events
|
22
|
+
|
23
|
+
attr_reader :events, :threads
|
24
|
+
|
25
|
+
# Produce a new events system.
|
26
|
+
def initialize
|
27
|
+
@events = Hash.new
|
28
|
+
end
|
29
|
+
|
30
|
+
# Await an event, and upon its occurrence, execute a block of code. It
|
31
|
+
# cannot get much simpler than such.
|
32
|
+
#
|
33
|
+
# @param [Symbol] event The event for which to wait.
|
34
|
+
# @param [Symbol] hook The identity of this hook.
|
35
|
+
#
|
36
|
+
# @yield [...] The arguments which will be yielded to the block vary by
|
37
|
+
# event. Consult with the {file:docs/Events.md events specification}.
|
38
|
+
def nut_catch(event, hook, &prc)
|
39
|
+
|
40
|
+
# Create a collection in the events hash for this event if one does not
|
41
|
+
# already exist.
|
42
|
+
@events[event] ||= []
|
43
|
+
|
44
|
+
# Append this hook.
|
45
|
+
@events[event] << [hook, prc]
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
# Execute an event, and call all the blocks of code which are hooked onto it,
|
50
|
+
# if any, passing to each the provided arguments.
|
51
|
+
#
|
52
|
+
# @param [Symbol] event The event which to execute.
|
53
|
+
# @param [Array<>] args The arguments which to pass to each block. (splat)
|
54
|
+
def nut_throw(event, *args)
|
55
|
+
|
56
|
+
# If a collection for this event exists, iterate through it.
|
57
|
+
if @events.include? event
|
58
|
+
|
59
|
+
@events[event].each do |hook|
|
60
|
+
hook[1].call(*args)
|
61
|
+
end
|
62
|
+
|
63
|
+
end # if @events.include? event
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# Delete a hook from an event.
|
68
|
+
#
|
69
|
+
# @param [Symbol] event The event for which this hook is waiting.
|
70
|
+
# @param [Symbol] hook The hook.
|
71
|
+
def nut_smash(event, hook)
|
72
|
+
if @events.include? event
|
73
|
+
@events[event].each do |h| # iterate through the hooks
|
74
|
+
if h[0] == hook
|
75
|
+
@events[event].delete([h[0], h[1]]) and next
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end # if @events.include? event
|
79
|
+
end
|
80
|
+
|
81
|
+
end # class Events
|
82
|
+
|
83
|
+
end # module Walnut
|
84
|
+
|
85
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,49 @@
|
|
1
|
+
begin
|
2
|
+
require "readline"
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
module Walnut
|
7
|
+
|
8
|
+
module Input
|
9
|
+
|
10
|
+
# Readline input plugin
|
11
|
+
#
|
12
|
+
# Must implement #read, #gets, and #eof?
|
13
|
+
class Readline
|
14
|
+
|
15
|
+
attr_reader :input_object
|
16
|
+
|
17
|
+
def initialize(parent)
|
18
|
+
@walnut = parent
|
19
|
+
@input_object = ::Readline
|
20
|
+
end
|
21
|
+
|
22
|
+
# Read a line from input
|
23
|
+
#
|
24
|
+
# @return [String,NilClass] A line read from the input, or nil if the user canceled the input with \C-d
|
25
|
+
#
|
26
|
+
# @note The instance variable @eof is set to nil when EOF has been reached, see #eof?
|
27
|
+
#
|
28
|
+
def gets
|
29
|
+
@eof = @input_object.readline(@walnut[:input].prompt||Walnut[:input].prompt, @walnut[:input].history||[])
|
30
|
+
end
|
31
|
+
|
32
|
+
# Check if an EOF has been reached
|
33
|
+
#
|
34
|
+
# @return [TrueClass,FalseClass]
|
35
|
+
def eof?
|
36
|
+
(@eof.nil?) ? true : false
|
37
|
+
end
|
38
|
+
|
39
|
+
alias read gets
|
40
|
+
|
41
|
+
def close
|
42
|
+
@eof = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, Matthew Carey
|
2
|
+
# All rights reserved.
|
3
|
+
# Distributed under the terms of the MIT license (see LICENSE.md).
|
4
|
+
|
5
|
+
module Walnut
|
6
|
+
|
7
|
+
module Output
|
8
|
+
|
9
|
+
class Standard
|
10
|
+
|
11
|
+
# @note #output defaults to $stdout
|
12
|
+
attr_accessor :output
|
13
|
+
|
14
|
+
# Initialize an object
|
15
|
+
#
|
16
|
+
# @param [Walnut::Shell] parent The parent of this object.
|
17
|
+
#
|
18
|
+
def initialize(parent)
|
19
|
+
@walnut = parent
|
20
|
+
@output = $stdout
|
21
|
+
end
|
22
|
+
|
23
|
+
# Write a string to the output
|
24
|
+
#
|
25
|
+
# @param [#to_s] string The string that will be written to the output stream.
|
26
|
+
#
|
27
|
+
# @return [Numeric] The number of characters written to the stream.
|
28
|
+
def write(string)
|
29
|
+
@output.write(string.to_s)
|
30
|
+
string.to_s.length
|
31
|
+
end
|
32
|
+
|
33
|
+
# Write a string with a newline to the output.
|
34
|
+
#
|
35
|
+
# @see {Walnut::Output::Standard#write}
|
36
|
+
#
|
37
|
+
def puts(string)
|
38
|
+
write(string + "\n")
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
data/lib/walnut/shell.rb
CHANGED
@@ -8,16 +8,85 @@ module Walnut
|
|
8
8
|
class Shell
|
9
9
|
|
10
10
|
# Constructor.
|
11
|
-
def initialize
|
11
|
+
def initialize(&block)
|
12
|
+
# Set the default config to the global.
|
13
|
+
@config = Walnut.config.dup
|
14
|
+
|
15
|
+
# Start with the global hooks.
|
16
|
+
events = Walnut.ev.dup
|
17
|
+
define_singleton_method(:ev) { events }
|
18
|
+
|
19
|
+
instance_exec(@config, &block) if block_given?
|
20
|
+
|
12
21
|
end
|
13
22
|
|
23
|
+
|
14
24
|
# Configure the shell.
|
15
25
|
def configure
|
16
26
|
|
17
|
-
yield
|
27
|
+
yield @config if block_given?
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
# A shortcut to the configuration
|
32
|
+
#
|
33
|
+
# @param [#to_s] key The configuration key you are looking for
|
34
|
+
#
|
35
|
+
# @return [Object] The object that the configuration key points to
|
36
|
+
#
|
37
|
+
def [](key)
|
38
|
+
@config.send(key.to_s)
|
39
|
+
end
|
18
40
|
|
41
|
+
# A shortcut to assign configuration values.
|
42
|
+
#
|
43
|
+
# @param [#to_s] key The key you are looking up in the configuration.
|
44
|
+
# @param [Object] value The new value for the key in the configuration.
|
45
|
+
#
|
46
|
+
# @return [Object] The value passed to be assigned.
|
47
|
+
#
|
48
|
+
def []=(key,value)
|
49
|
+
@config.send(key.to_s << "=", value)
|
19
50
|
end
|
20
51
|
|
52
|
+
# Begin a session, crack being a cutesy way to allude to the name of the project.
|
53
|
+
#
|
54
|
+
# @param [IO] input This object should at least implement the interface for Input.
|
55
|
+
# @param [IO] output This object should at least implement the interface for Output.
|
56
|
+
#
|
57
|
+
# @return [Walnut::Shell] Return self.
|
58
|
+
#
|
59
|
+
def crack(input=@config[:input].interface, output=@config[:output].interface)
|
60
|
+
|
61
|
+
if input then @config[:input].interface = input end
|
62
|
+
if output then @config[:output].interface = output end
|
63
|
+
|
64
|
+
input ||= Walnut[:input].interface
|
65
|
+
output ||= Walnut[:output].interface
|
66
|
+
ev.nut_throw :cracking
|
67
|
+
loop do
|
68
|
+
ev.nut_throw :before_read
|
69
|
+
text = input.gets
|
70
|
+
|
71
|
+
if input.eof?
|
72
|
+
ev.nut_throw :eof, self
|
73
|
+
|
74
|
+
# This has to be unset in a hook to recover from the EOF
|
75
|
+
break if input.eof?
|
76
|
+
end
|
77
|
+
|
78
|
+
ev.nut_throw :after_read, text
|
79
|
+
|
80
|
+
ev.nut_throw :before_parse, text
|
81
|
+
ast = nil #Parse -- ast == Abstract Syntax Tree. This is basically dependant on how the parser handles it.
|
82
|
+
# -- There is no definite interface for this because of the vast differences in parsers/lexers.
|
83
|
+
ev.nut_throw :after_parse, ast
|
84
|
+
end
|
85
|
+
|
86
|
+
# Cute after session hook name.
|
87
|
+
Walnut.ev.nut_throw :scrambled
|
88
|
+
end
|
89
|
+
|
21
90
|
end # class Shell
|
22
91
|
|
23
92
|
end # module Walnut
|
data/lib/walnut/version.rb
CHANGED
data/sample/echo.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "walnut"
|
2
|
+
require "walnut/input/readline"
|
3
|
+
require "walnut/output/standard"
|
4
|
+
|
5
|
+
shell = Walnut::Shell.new do |conf|
|
6
|
+
conf.input.prompt = "echo> "
|
7
|
+
conf.input.interface = Walnut::Input::Readline.new(self)
|
8
|
+
|
9
|
+
conf.output.interface = Walnut::Output::Standard.new(self)
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
shell.ev.nut_catch(:cracking, :banner) do
|
14
|
+
shell[:output].interface.write <<EOF
|
15
|
+
Welcome to Walnut's first example `echo'! To exit the echoing session, press Ctrl-d or whatever your system
|
16
|
+
recognizes as "END OF INPUT".
|
17
|
+
EOF
|
18
|
+
end
|
19
|
+
|
20
|
+
shell.ev.nut_catch(:after_read, :echo) do |string|
|
21
|
+
shell[:output].interface.puts string
|
22
|
+
end
|
23
|
+
|
24
|
+
shell.ev.nut_catch(:after_read, :add_history) do |string|
|
25
|
+
shell[:input].history << string
|
26
|
+
end
|
27
|
+
|
28
|
+
shell.crack
|
data/sample/repl.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require "walnut"
|
2
|
+
require "walnut/input/readline"
|
3
|
+
require "walnut/output/standard"
|
4
|
+
require "coderay"
|
5
|
+
require "pp"
|
6
|
+
|
7
|
+
shell = Walnut::Shell.new do |conf|
|
8
|
+
conf.input.interface = Walnut::Input::Readline.new(self)
|
9
|
+
|
10
|
+
conf.repl = Walnut::Configuration.new
|
11
|
+
conf.repl.depth = 0
|
12
|
+
conf.repl.lineno = 0
|
13
|
+
conf.repl.valid = false
|
14
|
+
conf.repl.buffer = ""
|
15
|
+
|
16
|
+
conf.output.interface = Walnut::Output::Standard.new(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
shell.ev.nut_catch(:before_read, :prompt_line_no) do
|
20
|
+
if shell[:repl].depth == 0
|
21
|
+
shell[:input].prompt = "[%i] (walnut)> " % shell[:repl].lineno
|
22
|
+
else
|
23
|
+
shell[:input].prompt = "[%i] (walnut) *#{" "*shell[:repl].depth}#{" "}" % shell[:repl].lineno
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
shell.ev.nut_catch(:after_read, :push_to_buffer) do |text|
|
28
|
+
shell[:repl].buffer << text + "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
shell.ev.nut_catch(:after_read, :push_to_history) do |text|
|
32
|
+
shell[:input].history << text
|
33
|
+
end
|
34
|
+
|
35
|
+
shell.ev.nut_catch(:after_read, :validate_code) do |text|
|
36
|
+
begin
|
37
|
+
catch :valid do
|
38
|
+
eval "BEGIN { throw :valid }\n#{shell[:repl].buffer}"
|
39
|
+
end
|
40
|
+
shell[:repl].valid = true
|
41
|
+
rescue SyntaxError
|
42
|
+
shell[:repl].valid = false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
shell.ev.nut_catch(:after_read, :transform_line) do |text|
|
47
|
+
shell[:output].interface.write("\e[s\e[A#{shell[:input].prompt}#{CodeRay.scan(text, :ruby).term}\e8")
|
48
|
+
end
|
49
|
+
|
50
|
+
shell.ev.nut_catch(:after_read, :evaluate) do |text|
|
51
|
+
if shell[:repl].valid
|
52
|
+
shell[:output].interface.write("=> #{CodeRay.scan((eval shell[:repl].buffer, TOPLEVEL_BINDING).pretty_inspect, :ruby).term}".concat("\n").sub(/\n+$/, "\n"))
|
53
|
+
shell[:repl].valid = false
|
54
|
+
shell[:repl].buffer = ""
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
shell.ev.nut_catch(:after_read, :increase_line) do |text|
|
59
|
+
if shell[:repl].buffer == ""
|
60
|
+
shell[:repl].lineno += 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
shell.crack
|
data/spec/events_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, Matthew Carey
|
2
|
+
# All rights reserved.
|
3
|
+
# Distributed under the terms of the MIT license (see LICENSE.md).
|
4
|
+
require(File.expand_path('../helper.rb', __FILE__))
|
5
|
+
|
6
|
+
require 'walnut'
|
7
|
+
|
8
|
+
describe 'Walnut::Events' do
|
9
|
+
|
10
|
+
@events = Walnut::Events.new
|
11
|
+
|
12
|
+
it 'should create a hook with #nut_catch' do
|
13
|
+
@events.nut_catch(:foo, :fooness) { nil }.should.not.equal nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should execute an event with #nut_throw' do
|
17
|
+
@fail = true
|
18
|
+
@events.nut_catch(:rawr, :nyan) { @fail = false }
|
19
|
+
@events.nut_throw(:rawr)
|
20
|
+
sleep 0.1
|
21
|
+
@fail.should.not.be.true
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should destroy a hook with #nut_smash' do
|
25
|
+
@succeed = true
|
26
|
+
@events.nut_catch(:meow, :moo) { @succeed = false }
|
27
|
+
@events.nut_smash(:meow, :moo)
|
28
|
+
@events.nut_throw(:meow)
|
29
|
+
@succeed.should.be.true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should separate events based on how and where they were added' do
|
33
|
+
@result1 = ""
|
34
|
+
@result2 = false
|
35
|
+
@result3 = false
|
36
|
+
|
37
|
+
Walnut.ev.nut_catch(:im_a, :global_gnu) { @result1 << "gnu" }
|
38
|
+
|
39
|
+
shell1 = Walnut::Shell.new
|
40
|
+
shell2 = Walnut::Shell.new
|
41
|
+
|
42
|
+
shell1.ev.nut_catch(:gnu, :local_gnu) { @result2 = :open_source }
|
43
|
+
shell2.ev.nut_catch(:gnu, :local_gnu) { @result3 = :not_unix }
|
44
|
+
|
45
|
+
[shell1, shell2 ].each do |s|
|
46
|
+
[:gnu, :im_a].each {|n| s.ev.nut_throw(n) }
|
47
|
+
end
|
48
|
+
|
49
|
+
@result1.should == "gnugnu"
|
50
|
+
@result2.should == :open_source
|
51
|
+
@result3.should == :not_unix
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
data/spec/helper.rb
ADDED
data/spec/input_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
$:.unshift File.join [File.expand_path(File.dirname __FILE__), "../lib"]
|
2
|
+
|
3
|
+
require "walnut"
|
4
|
+
require "walnut/input/readline"
|
5
|
+
require "stringio"
|
6
|
+
require "tempfile"
|
7
|
+
|
8
|
+
INPUT_STRING = "Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo\n"
|
9
|
+
|
10
|
+
describe "Walnut Readline Input" do
|
11
|
+
|
12
|
+
@walnut = Walnut::Shell.new
|
13
|
+
@walnut.configure do |c|
|
14
|
+
c.input = Walnut::Configuration.new
|
15
|
+
c.input.prompt = ">>> "
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
File.open(".walnut_test.txt", "w") {|f| f.write INPUT_STRING }
|
20
|
+
@input = Walnut::Input::Readline.new(@walnut)
|
21
|
+
@input.input_object.input = File.open(".walnut_test.txt", "r")
|
22
|
+
@input.input_object.output = File.open(".walnut_output.txt", "w+")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "implements the read and gets function in the same manner" do
|
26
|
+
@input.gets.should == INPUT_STRING.chomp
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should output a prompt based on the provided configuration" do
|
30
|
+
@input.gets
|
31
|
+
File.read(".walnut_output.txt").should == (@walnut[:input].prompt + INPUT_STRING)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should use the default prompt if there is no instance value for a prompt" do
|
35
|
+
@walnut[:input].prompt = false
|
36
|
+
@input.gets
|
37
|
+
File.read(".walnut_output.txt").should == (Walnut[:input].prompt + INPUT_STRING)
|
38
|
+
end
|
39
|
+
|
40
|
+
after do
|
41
|
+
@input.input_object.input = STDIN
|
42
|
+
@input.input_object.output = STDOUT
|
43
|
+
File.unlink(".walnut_test.txt", ".walnut_output.txt")
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/spec/output_spec.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.expand_path(File.dirname __FILE__) << "../lib"
|
4
|
+
|
5
|
+
require "walnut"
|
6
|
+
require "walnut/output/standard"
|
7
|
+
|
8
|
+
describe "Walnut Output Standard plugin" do
|
9
|
+
|
10
|
+
@output = Walnut::Output::Standard.new(Walnut::Shell.new)
|
11
|
+
|
12
|
+
it "writes to the stream based on the object in #output" do
|
13
|
+
string1, string2 = "", ""
|
14
|
+
string_io1, string_io2 = StringIO.new(string1), StringIO.new(string2)
|
15
|
+
|
16
|
+
# Set up a StringIO to recieve
|
17
|
+
@output.output = string_io1
|
18
|
+
@output.puts "I'm a gnu!"
|
19
|
+
|
20
|
+
# Set up a different StringIO to recieve
|
21
|
+
@output.output = string_io2
|
22
|
+
@output.puts "Soy un ñu!"
|
23
|
+
|
24
|
+
# If everything worked, the strings should be in their respective objects.
|
25
|
+
string1.should == "I'm a gnu!\n"
|
26
|
+
string2.should == "Soy un ñu!\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "tells you how many characters you write to the stream" do
|
30
|
+
string1 = "PNEUMONOULTRAMICROSCOPICSILICOVOLCANOCONIOSIS"
|
31
|
+
string2 = "HEPATICOCHOLANGIOCHOLECYSTENTEROSTOMIES"
|
32
|
+
|
33
|
+
string_io = StringIO.new("")
|
34
|
+
|
35
|
+
@output.output = string_io
|
36
|
+
|
37
|
+
@output.write(string1).should == string1.length
|
38
|
+
@output.puts(string2).should == (string2.length+1)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/walnut.gemspec
CHANGED
@@ -15,11 +15,11 @@ Gem::Specification.new do |gem|
|
|
15
15
|
|
16
16
|
gem.authors = ['Autumn Perrault', 'Matthew Carey']
|
17
17
|
gem.email = ['xoeverlux@gmail.com', 'matthew.b.carey@gmail.com']
|
18
|
-
gem.summary = '
|
18
|
+
gem.summary = 'The crunchy shell building framework.'
|
19
19
|
gem.description = 'A simple, highly customizable shell for Ruby 1.9.'
|
20
20
|
gem.homepage = 'http://git.io/walnutrb'
|
21
21
|
|
22
|
-
files = `git ls-files`.split($/); files.delete(
|
22
|
+
files = `git ls-files`.split($/); %w{.template.rb .travis.yml .gitignore}.each {|x| files.delete(x) }
|
23
23
|
gem.files = files
|
24
24
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
25
25
|
gem.require_paths = ['lib']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: walnut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-01-
|
13
|
+
date: 2013-01-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bacon
|
@@ -42,10 +42,20 @@ files:
|
|
42
42
|
- README.md
|
43
43
|
- Rakefile
|
44
44
|
- docs/interfaces/Input.md
|
45
|
+
- docs/interfaces/Output.md
|
45
46
|
- lib/walnut.rb
|
46
|
-
- lib/walnut/
|
47
|
+
- lib/walnut/configuration.rb
|
48
|
+
- lib/walnut/events.rb
|
49
|
+
- lib/walnut/input/readline.rb
|
50
|
+
- lib/walnut/output/standard.rb
|
47
51
|
- lib/walnut/shell.rb
|
48
52
|
- lib/walnut/version.rb
|
53
|
+
- sample/echo.rb
|
54
|
+
- sample/repl.rb
|
55
|
+
- spec/events_spec.rb
|
56
|
+
- spec/helper.rb
|
57
|
+
- spec/input_spec.rb
|
58
|
+
- spec/output_spec.rb
|
49
59
|
- walnut.gemspec
|
50
60
|
homepage: http://git.io/walnutrb
|
51
61
|
licenses: []
|
@@ -70,6 +80,10 @@ rubyforge_project:
|
|
70
80
|
rubygems_version: 1.8.23
|
71
81
|
signing_key:
|
72
82
|
specification_version: 3
|
73
|
-
summary:
|
74
|
-
test_files:
|
83
|
+
summary: The crunchy shell building framework.
|
84
|
+
test_files:
|
85
|
+
- spec/events_spec.rb
|
86
|
+
- spec/helper.rb
|
87
|
+
- spec/input_spec.rb
|
88
|
+
- spec/output_spec.rb
|
75
89
|
has_rdoc:
|