walnut 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/noxgirl/walnut.png?branch=master)](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:
|