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.



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

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

Instance Attribute Details

#commandsObject (readonly)

Returns the value of attribute commands.



38
39
40
# File 'lib/consolize.rb', line 38

def commands
  @commands
end

#storeObject (readonly)

Returns the value of attribute store.



38
39
40
# File 'lib/consolize.rb', line 38

def store
  @store
end

Instance Method Details

#add_command(pattern) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/consolize.rb', line 105

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



82
83
84
# File 'lib/consolize.rb', line 82

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

#complete(str) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/consolize.rb', line 45

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



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

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

#exitObject



126
127
128
# File 'lib/consolize.rb', line 126

def exit
  @run = false
end

#on(*pattern, &block) ⇒ Object



92
93
94
95
96
97
# File 'lib/consolize.rb', line 92

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.



101
102
103
# File 'lib/consolize.rb', line 101

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.



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

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



117
118
119
120
121
122
123
124
# File 'lib/consolize.rb', line 117

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



86
87
88
89
90
# File 'lib/consolize.rb', line 86

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



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

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