pal 0.0.1
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/bin/pal +5 -0
- data/lib/pal.rb +105 -0
- metadata +49 -0
data/bin/pal
ADDED
data/lib/pal.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require "readline"
|
2
|
+
|
3
|
+
# Public: Exposes a simple read-eval-print loop interface.
|
4
|
+
module Pal
|
5
|
+
# Public: The current version of Pal.
|
6
|
+
Version = "0.0.1"
|
7
|
+
|
8
|
+
# Public: Defines the evaluation context. All instance methods defined in
|
9
|
+
# this class are made available as top-level methods during evaluation.
|
10
|
+
class Context
|
11
|
+
# Internal: Stores the result of the last-evaluated expression.
|
12
|
+
attr_reader :_
|
13
|
+
|
14
|
+
# Internal: Provides a less verbose string representation for `Context`s.
|
15
|
+
def inspect
|
16
|
+
"Context"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: Creates a REPL instance.
|
21
|
+
class REPL
|
22
|
+
# Public: Gets the name of the REPL instance, used to generate the prompt
|
23
|
+
# text and debugging information.
|
24
|
+
attr_reader :name
|
25
|
+
|
26
|
+
# Public: Gets the evaluation context associated with the REPL instance.
|
27
|
+
attr_reader :context
|
28
|
+
|
29
|
+
# Public: Gets the result of the last-evaluated expression.
|
30
|
+
attr_reader :result
|
31
|
+
|
32
|
+
class << self
|
33
|
+
# Internal: Gets the current REPL instance.
|
34
|
+
attr_reader :messenger
|
35
|
+
|
36
|
+
# Public: Creates a new REPL instance. The `messenger` class instance
|
37
|
+
# variable is used by the REPL instance to correctly set and expose
|
38
|
+
# the result of the last-evaluated expression to the evaluation context.
|
39
|
+
def create(name = "pal", context = Context.new)
|
40
|
+
@messenger = new(name, context)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(name, context)
|
45
|
+
@name = name
|
46
|
+
@context = context
|
47
|
+
@line = 1
|
48
|
+
@statements = []
|
49
|
+
end
|
50
|
+
|
51
|
+
# Public: Starts the REPL. The REPL will persist until an `exit` signal
|
52
|
+
# is received.
|
53
|
+
def loop
|
54
|
+
catch :exit do
|
55
|
+
read while true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: Reads, evaluates, and prints a line of Ruby code. If the line is
|
60
|
+
# `exit` or `quit`, an `exit` signal is sent and the loop terminates. If an
|
61
|
+
# interrupt is sent via Control-C, a blank line is printed before exiting.
|
62
|
+
# Multiple lines of code may be evaluated by terminating each line with an
|
63
|
+
# escape character (`\`).
|
64
|
+
def read(prompt = @name)
|
65
|
+
@error = nil
|
66
|
+
@input = Readline.readline("#{prompt}> ", true)
|
67
|
+
throw :exit if @input.nil? || %w{exit quit}.include?(@input)
|
68
|
+
unless @input.empty?
|
69
|
+
@statements << @input
|
70
|
+
if @statements.last[-1] == "\\"
|
71
|
+
@statements.last.chop!
|
72
|
+
read ?. * @name.size
|
73
|
+
else
|
74
|
+
@input = @statements.join($/)
|
75
|
+
@statements.clear
|
76
|
+
evaluate @input
|
77
|
+
print @result
|
78
|
+
end
|
79
|
+
end
|
80
|
+
rescue Interrupt
|
81
|
+
puts
|
82
|
+
end
|
83
|
+
|
84
|
+
# Public: Evaluates a line of code in the current context. If an error was
|
85
|
+
# raised, the stack trace is printed. To reduce noise, all lines containing
|
86
|
+
# the current file name are removed.
|
87
|
+
def evaluate(value)
|
88
|
+
@result = eval(value, @context.instance_eval { binding }, "(#{@name})", @line)
|
89
|
+
@context.instance_variable_set(:@_, REPL.messenger.result)
|
90
|
+
rescue Exception => exception
|
91
|
+
@error = true
|
92
|
+
stack = exception.backtrace.take_while { |line| not line.include? File.basename(__FILE__) }
|
93
|
+
stack.unshift exception.message
|
94
|
+
warn %Q{#{exception.class}: #{stack.join($/ + " " * 4)}}
|
95
|
+
ensure
|
96
|
+
@line += 1
|
97
|
+
end
|
98
|
+
|
99
|
+
# Public: Prints the last output, prepending the output symbol to a
|
100
|
+
# human-readable representation of the result.
|
101
|
+
def print(result)
|
102
|
+
puts "=> #{result.inspect}" unless @error
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kit Cambridge
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-24 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Pal is a miniature Ruby REPL, similar to IRB. It's useful for creating
|
15
|
+
project-specific shells.
|
16
|
+
email: kitcambridge@me.com
|
17
|
+
executables:
|
18
|
+
- pal
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- bin/pal
|
23
|
+
- lib/pal.rb
|
24
|
+
homepage: http://github.com/kitcambridge/pal
|
25
|
+
licenses:
|
26
|
+
- MIT
|
27
|
+
post_install_message:
|
28
|
+
rdoc_options: []
|
29
|
+
require_paths:
|
30
|
+
- lib
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ! '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubyforge_project:
|
45
|
+
rubygems_version: 1.8.11
|
46
|
+
signing_key:
|
47
|
+
specification_version: 3
|
48
|
+
summary: A miniature Ruby shell.
|
49
|
+
test_files: []
|