harp 0.2.4 → 0.2.6

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/examples/usage.rb +10 -10
  2. data/lib/harp.rb +41 -74
  3. metadata +4 -4
data/examples/usage.rb CHANGED
@@ -11,33 +11,33 @@ class UsefulThing
11
11
  include Harp
12
12
 
13
13
  # Set it up
14
- setup_repl do |repl|
14
+ setup_harp do |harp|
15
15
 
16
- on("help") do
17
- commands = repl.commands
16
+ command("help") do
17
+ commands = harp.command_names
18
18
  puts "* Available commands: " << commands.sort.join(" ")
19
19
  puts "* Tab completion works for commands."
20
20
  end
21
21
 
22
22
  # Harp provides a "quit" command by default, but you can
23
23
  # override it to add value.
24
- on("quit") do
24
+ command("quit") do
25
25
  puts "Farewell to the girl with the sun in her eyes."
26
26
  exit
27
27
  end
28
28
 
29
- # Set up a handler for a command where the first token is "!"
30
- # I.e., shell out like Vim does.
31
- on_bang do |args|
32
- system args.first
33
- end
29
+ ## Set up a handler for a command where the first token is "!"
30
+ ## I.e., shell out like Vim does.
31
+ #on_bang do |args|
32
+ #system args.first
33
+ #end
34
34
 
35
35
  # define a command that calls an instance method of your class.
36
36
  # The block parameter is always an array, even if your regex
37
37
  # had only one match group.
38
38
  # This command will only accept a single-word argument (no
39
39
  # whitespace allowed).
40
- on(/use (\S+)$/) do |args|
40
+ command("use", :adverb) do |args|
41
41
  self.use(args.first)
42
42
  end
43
43
 
data/lib/harp.rb CHANGED
@@ -5,24 +5,24 @@ require "readline"
5
5
  Readline.completion_append_character = nil
6
6
  #Readline.basic_word_break_characters = ""
7
7
 
8
+ require "harp/dispatcher"
8
9
 
9
10
  module Harp
10
11
  def self.included(mod)
11
12
  mod.module_eval do
12
- @repl = REPL.new
13
- def self.repl
14
- @repl
15
- end
13
+ @dispatcher = Dispatcher.new
16
14
 
17
- def self.setup_repl(&block)
18
- repl = @repl
19
- @repl.on("quit") do
20
- repl.exit
21
- end
22
- @repl.on("") do
23
- puts "Giving me the silent treatment, eh?"
15
+ def self.setup_harp(&block)
16
+ dispatcher = @dispatcher
17
+ # This should either be baked in to REPL, or non-existent.
18
+ @dispatcher.command("quit") do
19
+ exit
24
20
  end
25
- @repl.instance_exec(repl, &block)
21
+ @dispatcher.instance_exec(dispatcher, &block)
22
+ end
23
+
24
+ def self.repl
25
+ REPL.new(@dispatcher)
26
26
  end
27
27
 
28
28
  def repl
@@ -34,9 +34,9 @@ module Harp
34
34
  class REPL
35
35
 
36
36
  attr_reader :store, :commands
37
- def initialize
38
- @patterns = {}
39
- @commands = Set.new
37
+ def initialize(dispatcher)
38
+ @dispatcher = dispatcher
39
+ @commands = dispatcher.commands.keys
40
40
  Readline.completion_proc = self.method(:complete)
41
41
  end
42
42
 
@@ -45,29 +45,27 @@ module Harp
45
45
  when /^\s*!/
46
46
  # if we're in the middle of a bang-exec command, completion
47
47
  # should look at the file system.
48
- self.dir_complete(str)
48
+ self.complete_path(str)
49
49
  else
50
50
  # otherwise use the internal dict.
51
- self.term_complete(str)
51
+ self.complete_term(str)
52
52
  end
53
53
  end
54
54
 
55
- def dir_complete(str)
55
+ def complete_path(str)
56
56
  Dir.glob("#{str}*")
57
57
  end
58
58
 
59
- def term_complete(str)
59
+ def complete_term(str)
60
60
  # Terms can be either commands or indexes into the configuration
61
61
  # data structure. No command contains a ".", so that's the test
62
62
  # we use to distinguish.
63
63
  bits = str.split(".")
64
64
  if bits.size > 1
65
- # Somebody should have documented this when he wrote it, because
66
- # he now does not remember exactly what he was trying to achieve.
67
- # He thinks that it's an attempt to allow completion of either
68
- # full configuration index strings, or of component parts.
69
- # E.g., if the configuration contains foo.bar.baz, this code
70
- # will offer both "foo" and "foo.bar.baz" as completions for "fo".
65
+ # An attempt to allow completion of either full configuration index
66
+ # strings, or of component parts. E.g., if the configuration contains
67
+ # foo.bar.baz, this code will offer both "foo" and "foo.bar.baz"
68
+ # as completions for "fo".
71
69
  v1 = @completions.grep(/^#{Regexp.escape(str)}/)
72
70
  v2 = @completions.grep(/^#{Regexp.escape(bits.last)}/)
73
71
  (v1 + v2.map {|x| (bits.slice(0..-2) << x).join(".") }).uniq
@@ -87,63 +85,32 @@ module Harp
87
85
  str.gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/, "")
88
86
  end
89
87
 
90
- def on(*pattern, &block)
91
- pattern.flatten.each do |pattern|
92
- @patterns[pattern] = block
93
- self.add_command(pattern)
94
- end
95
- end
96
-
97
- # Helper for defining the action for the "!" command.
98
- # Typically used to shell out, a la Vim.
99
- def on_bang(&block)
100
- on(/^\!\s*(.*)$/, &block)
101
- end
102
-
103
- def add_command(pattern)
104
- if pattern.is_a?(String)
105
- @commands << pattern
106
- else
107
- bits = pattern.source.split(" ")
108
- # TODO: figure out why you did this, then document it.
109
- if bits.size > 1
110
- @commands << bits.first
111
- end
112
- end
113
- end
114
-
115
88
  def run(context)
116
89
  @completions = context.completions rescue Set.new
117
90
  @run = true
118
91
  puts
119
- while @run && line = Readline.readline("<3: ", true)
120
- self.parse(context, line.chomp)
121
- end
122
- end
92
+ while @run && (line = Readline.readline("<3: ", true).strip)
93
+ if line[0] == "!"
94
+ system(line.slice(1..-1))
95
+ next
96
+ end
123
97
 
124
- def exit
125
- @run = false
126
- end
98
+ if line.empty?
99
+ next
100
+ end
127
101
 
128
- # Attempt to find a registered command that matches the input
129
- # string. Upon failure, print an encouraging message.
130
- def parse(context, input_string)
131
- _p, block= @patterns.detect do |pattern, block|
132
- pattern === input_string
133
- end
134
- if block
135
- # Perlish global ugliness necessitated by the use of
136
- # Enumerable#detect above. FIXME.
137
- if $1
138
- # if the regex had a group (based on the assumption that $1
139
- # represents the result of the === that matched), call the block
140
- # with all the group matches as arguments.
141
- context.instance_exec($~[1..-1], &block)
102
+ name, *args = line.split(/\s+/)
103
+
104
+ # TODO: check for bang command
105
+ if command = @dispatcher.commands[name]
106
+ if block = command.block_for(args)
107
+ context.instance_exec(args, &block)
108
+ else
109
+ puts "invalid arguments for command"
110
+ end
142
111
  else
143
- context.instance_eval(&block)
112
+ puts "command not found"
144
113
  end
145
- else
146
- puts "command not found"
147
114
  end
148
115
  end
149
116
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-31 00:00:00.000000000 Z
12
+ date: 2012-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: starter
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.1.0
21
+ version: 0.1.1
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 0.1.0
29
+ version: 0.1.1
30
30
  description:
31
31
  email:
32
32
  executables: []