mayl 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,17 @@ module Mayl
2
2
  # Public: The Commands module is a namespace for all the commands that Mayl
3
3
  # uses.
4
4
  module Commands
5
+ def self.autocomplete(line, env)
6
+ key = line.split.first || ''
7
+
8
+ # Try to get namespaces or keys
9
+ keys = env.autocomplete(key)
10
+ return keys if keys.any?
11
+
12
+ # If not, autocomplete commands
13
+ opts = constants.map(&:to_s).map(&:downcase)
14
+ opts.grep(/^#{Regexp.escape(key)}/)
15
+ end
5
16
  end
6
17
  end
7
18
 
@@ -14,6 +14,7 @@ module Mayl
14
14
  # path - the path to cd in
15
15
  def initialize(env, path)
16
16
  @env = env
17
+ path = path.split('.').reject(&:empty?).compact.join('.') if path =~ /\w/
17
18
  @path = path
18
19
  end
19
20
 
@@ -29,6 +30,8 @@ module Mayl
29
30
  when "."
30
31
  @env.namespace = ""
31
32
  else
33
+ check_namespace!
34
+
32
35
  if @env.namespace.empty?
33
36
  @env.namespace = @path
34
37
  else
@@ -37,6 +40,19 @@ module Mayl
37
40
  end
38
41
  nil
39
42
  end
43
+
44
+ # Public: Checks that you're not trying to enter a leaf.
45
+ #
46
+ # Raises an ArgumentError if you are.
47
+ def check_namespace!
48
+ namespace = [@env.namespace, @path].reject(&:empty?).join('.')
49
+ matches = @env.peek(namespace).compact
50
+
51
+ if matches.empty?
52
+ key = @path.split('.').last
53
+ raise ArgumentError, "Can't cd to #{key} -- it's a leaf"
54
+ end
55
+ end
40
56
  end
41
57
  end
42
58
  end
@@ -19,9 +19,7 @@ module Mayl
19
19
  #
20
20
  # Returns nil.
21
21
  def execute
22
- locales.map { |locale|
23
- locale.peek(@env.namespace)
24
- }.flatten.uniq.each do |option|
22
+ @env.peek.each do |option|
25
23
  print "#{option} "
26
24
  end
27
25
  nil
@@ -6,6 +6,25 @@ module Mayl
6
6
  attr_accessor :last_value
7
7
  attr_accessor :namespace
8
8
 
9
+ # Public: Autocompletes a key looking at the current namespace and
10
+ # their contents.
11
+ #
12
+ # key - the partial key to consult in the namespace.
13
+ #
14
+ # Returns an Array of results.
15
+ def autocomplete(key)
16
+ peek.grep(/^#{Regexp.escape(key)}/)
17
+ end
18
+
19
+ # Public: Returns the keys inside a namespace, by default ours.
20
+ #
21
+ # namespace - the namespace to peek in. It's ours by default.
22
+ #
23
+ # Returns an Array of results.
24
+ def peek(namespace=self.namespace)
25
+ locales.map { |locale| locale.peek(namespace) }.flatten.uniq
26
+ end
27
+
9
28
  # Public: Initializes a new Env loading the locales from a path.
10
29
  def initialize(path)
11
30
  @locales = Loader.load(path)
@@ -1,3 +1,5 @@
1
+ require "readline"
2
+
1
3
  module Mayl
2
4
  # Public: The class responsible for reading user input, interpreting it and
3
5
  # executing associated commands.
@@ -18,19 +20,31 @@ module Mayl
18
20
  # Returns nothing.
19
21
  def start
20
22
  locales = @env.locales.map(&:name)
23
+ stty_save = `stty -g`.chomp
21
24
  prompt = "> "
22
25
  puts "Detected locales: #{locales.join(', ')}"
23
- while (print prompt; input = $stdin.gets)
24
- begin
25
- value = @parser.parse(input.chomp).execute
26
- @env.last_value = value
27
- @env.commit
28
- prompt = [@env.namespace, '> '].reject(&:empty?).join ' '
29
- rescue => e
30
- print "Error: #{e.message}"
31
- ensure
32
- print "\n"
26
+
27
+ env = @env
28
+ Readline.completion_proc = proc { |s| Commands.autocomplete(s, env) }
29
+ Readline.completion_append_character = ''
30
+ # Readline.completer_word_break_characters = 23.chr
31
+
32
+ begin
33
+ while input = Readline.readline(prompt, true)
34
+ begin
35
+ value = @parser.parse(input.chomp).execute
36
+ @env.last_value = value
37
+ @env.commit
38
+ prompt = [@env.namespace, '> '].reject(&:empty?).join ' '
39
+ rescue => e
40
+ print "Error: #{e.message}"
41
+ ensure
42
+ print "\n"
43
+ end
33
44
  end
45
+ rescue Interrupt
46
+ system("stty", stty_save)
47
+ exit
34
48
  end
35
49
  end
36
50
  end
@@ -1,4 +1,4 @@
1
1
  module Mayl
2
2
  # The version of the Mayl gem.
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
@@ -12,21 +12,30 @@ module Mayl
12
12
 
13
13
  it 'enters a directory' do
14
14
  @command = Cd.new @env, 'post.attributes'
15
+ @command.stubs(:check_namespace!)
15
16
  @command.execute
16
17
  @env.namespace.must_equal 'activerecord.models.post.attributes'
17
18
  end
18
19
 
19
20
  it 'goes down one level' do
20
21
  @command = Cd.new @env, '..'
22
+ @command.stubs(:check_namespace!)
21
23
  @command.execute
22
24
  @env.namespace.must_equal 'activerecord'
23
25
  end
24
26
 
25
27
  it 'goes to the root level' do
26
28
  @command = Cd.new @env, '.'
29
+ @command.stubs(:check_namespace!)
27
30
  @command.execute
28
31
  @env.namespace.must_equal ''
29
32
  end
33
+
34
+ it 'does not enter leaves' do
35
+ @env.stubs(:peek).returns []
36
+ @command = Cd.new @env, 'activerecord.models.post'
37
+ proc { @command.execute }.must_raise ArgumentError
38
+ end
30
39
  end
31
40
  end
32
41
  end
@@ -11,8 +11,7 @@ module Mayl
11
11
  end
12
12
 
13
13
  it 'prints the current keys inside the namespace' do
14
- @locales.first.expects(:peek).with('activerecord').returns ['models']
15
- @locales.last.expects(:peek).with('activerecord').returns ['attributes', 'models']
14
+ @env.expects(:peek).returns ['models', 'attributes']
16
15
 
17
16
  @command.expects(:print).with('models ')
18
17
  @command.expects(:print).with('attributes ')
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
  module Mayl
4
4
  describe Env do
5
5
  before do
6
- @locales = [stub, stub]
6
+ @locales = [stub(peek: [:baz]), stub(peek: [:bar])]
7
7
  Loader.expects(:load).with('my/path').returns @locales
8
8
  @env = Mayl::Env.new('my/path')
9
9
  end
@@ -19,6 +19,14 @@ module Mayl
19
19
 
20
20
  @env.commit
21
21
  end
22
+
23
+ it 'peeks in the locales' do
24
+ @env.peek.must_equal [:baz, :bar]
25
+ end
26
+
27
+ it 'autocompletes from a key' do
28
+ @env.autocomplete('ba').must_equal [:baz, :bar]
29
+ end
22
30
  end
23
31
  end
24
32
 
@@ -12,7 +12,7 @@ module Mayl
12
12
  @baz = stub
13
13
  @baz.expects(:execute)
14
14
 
15
- $stdin.expects(:gets).times(3).returns("foo bar\n", "baz lol\n", nil)
15
+ Readline.expects(:readline).times(3).returns("foo bar\n", "baz lol\n", nil)
16
16
 
17
17
  @repl.parser.expects(:parse).with('foo bar').returns @foo
18
18
  @repl.parser.expects(:parse).with('baz lol').returns @baz
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mayl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
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-04-17 00:00:00.000000000 Z
12
+ date: 2012-04-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yard