Class: Console

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConsole

Returns a new instance of Console.



42
43
44
45
46
# File 'lib/consolize.rb', line 42

def initialize
  @patterns = {}
  @commands = Set.new
  Readline.completion_proc = self.method(:complete)
end

Instance Attribute Details

#commandsObject (readonly)

Returns the value of attribute commands.



41
42
43
# File 'lib/consolize.rb', line 41

def commands
  @commands
end

#storeObject (readonly)

Returns the value of attribute store.



41
42
43
# File 'lib/consolize.rb', line 41

def store
  @store
end

Instance Method Details

#add_command(pattern) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/consolize.rb', line 108

def add_command(pattern)
  if pattern.is_a?(String)
    @commands << pattern
  else
    bits = pattern.source.split(" ")
    # TODO: figure out why you did this, then document it.
    if bits.size > 1
      @commands << bits.first
    end
  end
end

#command_complete(str) ⇒ Object



85
86
87
# File 'lib/consolize.rb', line 85

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

#complete(str) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/consolize.rb', line 48

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.dir_complete(str)
  else
    # otherwise use the internal dict.
    self.term_complete(str)
  end
end

#dir_complete(str) ⇒ Object



60
61
62
# File 'lib/consolize.rb', line 60

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

#exitObject



129
130
131
# File 'lib/consolize.rb', line 129

def exit
  @run = false
end

#on(*pattern, &block) ⇒ Object



95
96
97
98
99
100
# File 'lib/consolize.rb', line 95

def on(*pattern, &block)
  pattern.flatten.each do |pattern|
    @patterns[pattern] = block
    self.add_command(pattern)
  end
end

#on_bang(&block) ⇒ Object

Helper for defining the action for the “!” command. Typically used to shell out, a la Vim.



104
105
106
# File 'lib/consolize.rb', line 104

def on_bang(&block)
  on(/^\!\s*(.*)$/, &block)
end

#parse(context, input_string) ⇒ Object

Attempt to find a registered command that matches the input string. Upon failure, print an encouraging message.



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/consolize.rb', line 135

def parse(context, input_string)
  _p, block= @patterns.detect do |pattern, block|
    pattern === input_string
  end
  if block
    # Perlish global ugliness necessitated by the use of
    # Enumerable#detect above.  FIXME.
    if $1
      # if the regex had a group (based on the assumption that $1
      # represents the result of the === that matched), call the block
      # with all the group matches as arguments.
      context.instance_exec($~[1..-1], &block)
    else
      context.instance_eval(&block)
    end
  else
    puts "command not found"
  end
end

#run(context) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/consolize.rb', line 120

def run(context)
  @completions = context.completions rescue Set.new
  @run = true
  puts
  while @run && line = Readline.readline("<3: ", true)
    self.parse(context, line.chomp)
  end
end

#sanitize(str) ⇒ Object



89
90
91
92
93
# File 'lib/consolize.rb', line 89

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

#term_complete(str) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/consolize.rb', line 64

def term_complete(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
    # Somebody should have documented this when he wrote it, because
    # he now does not remember exactly what he was trying to achieve.
    # He thinks that it's 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