pal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/pal +5 -0
  2. data/lib/pal.rb +105 -0
  3. metadata +49 -0
data/bin/pal ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join File.expand_path(File.dirname __FILE__), *%w{.. lib pal}
4
+
5
+ Pal::REPL.create.loop
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: []