Class: Harp::REPL

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

Constant Summary collapse

Prompt =
"<3: "

Instance Method Summary collapse

Constructor Details

#initialize(command_manager) ⇒ REPL

Returns a new instance of REPL.



13
14
15
16
# File 'lib/harp/repl.rb', line 13

def initialize(command_manager)
  @command_manager = command_manager
  Readline.completion_proc = self.method(:complete)
end

Instance Method Details

#command_complete(str) ⇒ Object



57
58
59
# File 'lib/harp/repl.rb', line 57

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

#commandsObject



18
19
20
# File 'lib/harp/repl.rb', line 18

def commands
  @command_manager.commands.keys
end

#complete(str) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/harp/repl.rb', line 22

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



34
35
36
# File 'lib/harp/repl.rb', line 34

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

#complete_term(str) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/harp/repl.rb', line 38

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



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/harp/repl.rb', line 67

def run(context)
  @completions = context.completions rescue Set.new
  @run = true
  puts
  stty_save = `stty -g`.chomp
  trap("INT") { system "stty", stty_save; exit }
  while @run && (line = Readline.readline(Prompt, true).strip)
    # Treat ! as the shell out command
    if line[0] == "!"
      system(line.slice(1..-1))
      next
    end

    if line.empty?
      next
    end

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

    begin
      @command_manager.handle(name, args, context)
    rescue ArgumentError => e
      puts e.message
    end
  end
end

#sanitize(str) ⇒ Object



61
62
63
64
65
# File 'lib/harp/repl.rb', line 61

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