Class: Harp::REPL

Inherits:
Object
  • Object
show all
Defined in:
lib/harp.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dispatcher) ⇒ REPL

Returns a new instance of REPL.



37
38
39
40
41
# File 'lib/harp.rb', line 37

def initialize(dispatcher)
  @dispatcher = dispatcher
  @commands = dispatcher.commands.keys
  Readline.completion_proc = self.method(:complete)
end

Instance Attribute Details

#commandsObject (readonly)

Returns the value of attribute commands.



36
37
38
# File 'lib/harp.rb', line 36

def commands
  @commands
end

#storeObject (readonly)

Returns the value of attribute store.



36
37
38
# File 'lib/harp.rb', line 36

def store
  @store
end

Instance Method Details

#command_complete(str) ⇒ Object



78
79
80
# File 'lib/harp.rb', line 78

def command_complete(str)
  @commands.grep(/^#{Regexp.escape(str)}/) 
end

#complete(str) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/harp.rb', line 43

def complete(str)
  case Readline.line_buffer
  when /^\s*!/
    # if we're in the middle of a bang-exec command, completion
    # should look at the file system.
    self.complete_path(str)
  else
    # otherwise use the internal dict.
    self.complete_term(str)
  end
end

#complete_path(str) ⇒ Object



55
56
57
# File 'lib/harp.rb', line 55

def complete_path(str)
  Dir.glob("#{str}*")
end

#complete_term(str) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/harp.rb', line 59

def complete_term(str)
  # Terms can be either commands or indexes into the configuration
  # data structure.  No command contains a ".", so that's the test
  # we use to distinguish.
  bits = str.split(".")
  if bits.size > 1
    # An attempt to allow completion of either full configuration index
    # strings, or of component parts.  E.g., if the configuration contains
    # foo.bar.baz, this code will offer both "foo" and "foo.bar.baz"
    # as completions for "fo".
    v1 = @completions.grep(/^#{Regexp.escape(str)}/)
    v2 = @completions.grep(/^#{Regexp.escape(bits.last)}/)
    (v1 + v2.map {|x| (bits.slice(0..-2) << x).join(".") }).uniq
  else
    self.command_complete(str) +
      @completions.grep(/^#{Regexp.escape(str)}/)
  end
end

#run(context) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/harp.rb', line 88

def run(context)
  @completions = context.completions rescue Set.new
  @run = true
  puts
  while @run && (line = Readline.readline("<3: ", true).strip)
    if line[0] == "!"
      system(line.slice(1..-1))
      next
    end

    if line.empty?
      next
    end

    name, *args = line.split(/\s+/)

    # TODO: check for bang command
    if command = @dispatcher.commands[name]
      if block = command.block_for(args)
        context.instance_exec(args, &block)
      else
        puts "invalid arguments for command"
      end
    else
      puts "command not found"
    end
  end
end

#sanitize(str) ⇒ Object



82
83
84
85
86
# File 'lib/harp.rb', line 82

def sanitize(str)
  # ANSI code stripper regex cargo culted from
  # http://www.commandlinefu.com/commands/view/3584/remove-color-codes-special-characters-with-sed
  str.gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/, "")
end