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.
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: []