mayl 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +92 -0
- data/Rakefile +18 -0
- data/bin/mayl +5 -0
- data/lib/mayl.rb +12 -0
- data/lib/mayl/commands.rb +13 -0
- data/lib/mayl/commands/cd.rb +42 -0
- data/lib/mayl/commands/edit.rb +54 -0
- data/lib/mayl/commands/exit.rb +25 -0
- data/lib/mayl/commands/get.rb +59 -0
- data/lib/mayl/commands/ls.rb +40 -0
- data/lib/mayl/commands/set.rb +54 -0
- data/lib/mayl/env.rb +21 -0
- data/lib/mayl/loader.rb +25 -0
- data/lib/mayl/locale.rb +83 -0
- data/lib/mayl/parser.rb +20 -0
- data/lib/mayl/repl.rb +37 -0
- data/lib/mayl/version.rb +4 -0
- data/mayl.gemspec +24 -0
- data/test/mayl/commands/cd_test.rb +32 -0
- data/test/mayl/commands/edit_test.rb +19 -0
- data/test/mayl/commands/exit_test.rb +16 -0
- data/test/mayl/commands/get_test.rb +24 -0
- data/test/mayl/commands/ls_test.rb +24 -0
- data/test/mayl/commands/set_test.rb +22 -0
- data/test/mayl/env_test.rb +24 -0
- data/test/mayl/loader_test.rb +10 -0
- data/test/mayl/locale_test.rb +51 -0
- data/test/mayl/parser_test.rb +17 -0
- data/test/mayl/repl_test.rb +24 -0
- data/test/mayl_test.rb +7 -0
- data/test/support/ca.yml +4 -0
- data/test/support/en.yml +4 -0
- data/test/support/es.yml +4 -0
- data/test/test_helper.rb +5 -0
- metadata +182 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create use 1.9.3@mayl
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Josep M. Bach
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# mayl - a YAML console
|
2
|
+
|
3
|
+
Mayl is an anagram of YAML, and also a console to create, edit and maintain
|
4
|
+
YAML files in any kind of Ruby projects.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Install mayl yourself:
|
9
|
+
|
10
|
+
$ gem install mayl
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Mayl expects your YAML files to be organized like this: one file per locale
|
15
|
+
(`en.yml`, `es.yml`, `ca.yml`...) in a directory.
|
16
|
+
|
17
|
+
When it starts, it needs to know where to find all these YAML files, and it
|
18
|
+
looks by default under `./config/locales` but you can always run it like `mayl
|
19
|
+
some/other/dir` to override this.
|
20
|
+
|
21
|
+
$ mayl
|
22
|
+
Detected locales: ca, en, es
|
23
|
+
>
|
24
|
+
|
25
|
+
Now we'll set a new key by typing `set KEY` and typing in the translations:
|
26
|
+
|
27
|
+
> set activerecord.models.post
|
28
|
+
ca: Article
|
29
|
+
en: Post
|
30
|
+
es: Artículo
|
31
|
+
|
32
|
+
Set activerecord.models.post to Article (ca), Post (en) and Artículo (es)
|
33
|
+
>
|
34
|
+
|
35
|
+
Changes get written to the file immediately. We can consult a key any time,
|
36
|
+
and in case we see any error, correct it quickly with `edit LOCALE NEWVALUE`:
|
37
|
+
|
38
|
+
> get activerecord.models.post
|
39
|
+
ca: Article
|
40
|
+
en: Post
|
41
|
+
es: Artículo
|
42
|
+
> edit es Entrada
|
43
|
+
|
44
|
+
Set activerecord.models.post to Entrada (es)
|
45
|
+
>
|
46
|
+
|
47
|
+
### Namespaces
|
48
|
+
|
49
|
+
If you want to work for a while inside a namespace, let's say
|
50
|
+
`activerecord.models`, you can do so by `cd`-ing into it, and even `ls` the
|
51
|
+
existing keys:
|
52
|
+
|
53
|
+
> cd activerecord.models
|
54
|
+
activerecord.models > get post
|
55
|
+
ca: Article
|
56
|
+
en: Post
|
57
|
+
es: Entrada
|
58
|
+
activerecord.models > cd ..
|
59
|
+
activerecord > ls
|
60
|
+
models attributes
|
61
|
+
activerecord > cd ..
|
62
|
+
>
|
63
|
+
|
64
|
+
Cool way to navigate your YAML files huh?
|
65
|
+
|
66
|
+
### Other useful commands
|
67
|
+
|
68
|
+
* `exit`: Exits the console.
|
69
|
+
|
70
|
+
## Development
|
71
|
+
|
72
|
+
To run the tests:
|
73
|
+
|
74
|
+
$ rake
|
75
|
+
|
76
|
+
To build the documentation under the `doc` directory:
|
77
|
+
|
78
|
+
$ rake doc
|
79
|
+
|
80
|
+
## Contributing
|
81
|
+
|
82
|
+
1. Fork it
|
83
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
84
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
85
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
86
|
+
5. Create new Pull Request
|
87
|
+
|
88
|
+
## Who's this
|
89
|
+
|
90
|
+
This was made by [Josep M. Bach (Txus)](http://txustice.me) under the MIT
|
91
|
+
license. I'm [@txustice](http://twitter.com/txustice) on twitter (where you
|
92
|
+
should probably follow me!).
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'yard'
|
5
|
+
YARD::Config.load_plugin('yard-tomdoc')
|
6
|
+
YARD::Rake::YardocTask.new do |t|
|
7
|
+
t.files = ['lib/**/*.rb']
|
8
|
+
t.options = %w(-r README.md)
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rake/testtask'
|
12
|
+
Rake::TestTask.new do |t|
|
13
|
+
t.libs << "test"
|
14
|
+
t.test_files = FileList['./test/**/*_test.rb']
|
15
|
+
end
|
16
|
+
|
17
|
+
task :doc => :yard
|
18
|
+
task :default => :test
|
data/bin/mayl
ADDED
data/lib/mayl.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "mayl/version"
|
2
|
+
require "mayl/commands"
|
3
|
+
require "mayl/locale"
|
4
|
+
require "mayl/loader"
|
5
|
+
require "mayl/env"
|
6
|
+
require "mayl/parser"
|
7
|
+
require "mayl/repl"
|
8
|
+
|
9
|
+
# Public: Mayl is an anagram of YAML, and also a console to create, edit and
|
10
|
+
# maintain YAML files in any kind of Ruby projects.
|
11
|
+
module Mayl
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Mayl
|
2
|
+
# Public: The Commands module is a namespace for all the commands that Mayl
|
3
|
+
# uses.
|
4
|
+
module Commands
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'mayl/commands/set'
|
9
|
+
require 'mayl/commands/get'
|
10
|
+
require 'mayl/commands/edit'
|
11
|
+
require 'mayl/commands/cd'
|
12
|
+
require 'mayl/commands/exit'
|
13
|
+
require 'mayl/commands/ls'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Mayl
|
2
|
+
module Commands
|
3
|
+
# Public: The Cd command navigates through YAML namespaces.
|
4
|
+
#
|
5
|
+
# Example
|
6
|
+
#
|
7
|
+
# command = Cd.new(env, 'models.bla')
|
8
|
+
# command.execute
|
9
|
+
#
|
10
|
+
class Cd
|
11
|
+
# Public: Initializes a new Cd command.
|
12
|
+
#
|
13
|
+
# env - the global environment
|
14
|
+
# path - the path to cd in
|
15
|
+
def initialize(env, path)
|
16
|
+
@env = env
|
17
|
+
@path = path
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: Adds the path to the namespace.
|
21
|
+
#
|
22
|
+
# Returns nil.
|
23
|
+
def execute
|
24
|
+
case @path
|
25
|
+
when ".."
|
26
|
+
ns = @env.namespace.split('.')
|
27
|
+
ns.pop
|
28
|
+
@env.namespace = ns.join('.')
|
29
|
+
when "."
|
30
|
+
@env.namespace = ""
|
31
|
+
else
|
32
|
+
if @env.namespace.empty?
|
33
|
+
@env.namespace = @path
|
34
|
+
else
|
35
|
+
@env.namespace += '.' << @path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Mayl
|
2
|
+
module Commands
|
3
|
+
# Public: The Edit command quickly edits the last value consulted with Get
|
4
|
+
# or Set.
|
5
|
+
#
|
6
|
+
# Example
|
7
|
+
#
|
8
|
+
# command = Edit.new(env, 'es', 'Artículo')
|
9
|
+
# command.execute
|
10
|
+
#
|
11
|
+
class Edit
|
12
|
+
attr_reader :locale, :value
|
13
|
+
|
14
|
+
# Public: Initializes a new Get command.
|
15
|
+
#
|
16
|
+
# env - the global environment
|
17
|
+
# locale - the locale that we want to edit
|
18
|
+
# value - the value to set
|
19
|
+
def initialize(env, locale, value)
|
20
|
+
@env = env
|
21
|
+
@key = @env.last_value
|
22
|
+
raise ArgumentError, "You must get or set a key before calling edit" unless @key
|
23
|
+
@locale = locale
|
24
|
+
@value = value
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Executes the command, editing the @key for the given @locale.
|
28
|
+
#
|
29
|
+
# Returns the key.
|
30
|
+
def execute
|
31
|
+
locale = locales.detect do |locale|
|
32
|
+
locale.name.to_s == @locale.to_s
|
33
|
+
end
|
34
|
+
locale.set @key, @value
|
35
|
+
@key
|
36
|
+
end
|
37
|
+
|
38
|
+
#######
|
39
|
+
private
|
40
|
+
#######
|
41
|
+
|
42
|
+
# Public: Returns an Array with the locales of the environment.
|
43
|
+
def locales
|
44
|
+
@env.locales
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: Returns the given String key according to the qualified
|
48
|
+
# namespace we are in.
|
49
|
+
def qualified_key
|
50
|
+
[@env.namespace.to_s, @key].reject(&:empty?).compact.join('.')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Mayl
|
2
|
+
module Commands
|
3
|
+
# Public: The Exit command exits the program.
|
4
|
+
#
|
5
|
+
# Example
|
6
|
+
#
|
7
|
+
# command = Exit.new(env)
|
8
|
+
# command.execute
|
9
|
+
#
|
10
|
+
class Exit
|
11
|
+
# Public: Initializes a new Exit command.
|
12
|
+
#
|
13
|
+
# env - the global environment
|
14
|
+
def initialize(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Public: Exits the program.
|
18
|
+
#
|
19
|
+
# Returns nothing.
|
20
|
+
def execute
|
21
|
+
exit(0)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Mayl
|
2
|
+
module Commands
|
3
|
+
# Public: The Get command accepts a key and returns a summary of the
|
4
|
+
# values for that key in every locale.
|
5
|
+
#
|
6
|
+
# Example
|
7
|
+
#
|
8
|
+
# command = Get.new(env, 'activerecord.models.post')
|
9
|
+
# command.execute
|
10
|
+
# # Outputs:
|
11
|
+
# # ca: Article
|
12
|
+
# # es: Artículo
|
13
|
+
# # en: Post
|
14
|
+
#
|
15
|
+
class Get
|
16
|
+
attr_reader :key
|
17
|
+
|
18
|
+
# Public: Initializes a new Get command.
|
19
|
+
#
|
20
|
+
# env - the global environment
|
21
|
+
# key - the String key to get the value of
|
22
|
+
def initialize(env, key)
|
23
|
+
@env = env
|
24
|
+
@key = key
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Executes the command, iterating over each locale, asking the
|
28
|
+
# value for the key, and printing it out.
|
29
|
+
#
|
30
|
+
# Returns the key.
|
31
|
+
def execute
|
32
|
+
locales.each do |locale|
|
33
|
+
result = locale.get qualified_key
|
34
|
+
if result.is_a? String
|
35
|
+
print " #{locale.to_s}: #{result}\n"
|
36
|
+
else
|
37
|
+
print " #{locale.to_s}: (empty)\n"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
@key
|
41
|
+
end
|
42
|
+
|
43
|
+
#######
|
44
|
+
private
|
45
|
+
#######
|
46
|
+
|
47
|
+
# Public: Returns an Array with the locales of the environment.
|
48
|
+
def locales
|
49
|
+
@env.locales
|
50
|
+
end
|
51
|
+
|
52
|
+
# Public: Returns the given String key according to the qualified
|
53
|
+
# namespace we are in.
|
54
|
+
def qualified_key
|
55
|
+
[@env.namespace.to_s, @key].reject(&:empty?).compact.join('.')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Mayl
|
2
|
+
module Commands
|
3
|
+
# Public: The Cd command navigates through YAML namespaces.
|
4
|
+
#
|
5
|
+
# Example
|
6
|
+
#
|
7
|
+
# command = Ls.new(env)
|
8
|
+
# command.execute
|
9
|
+
#
|
10
|
+
class Ls
|
11
|
+
# Public: Initializes a new Cd command.
|
12
|
+
#
|
13
|
+
# env - the global environment
|
14
|
+
def initialize(env)
|
15
|
+
@env = env
|
16
|
+
end
|
17
|
+
|
18
|
+
# Public: Adds the path to the namespace.
|
19
|
+
#
|
20
|
+
# Returns nil.
|
21
|
+
def execute
|
22
|
+
locales.map { |locale|
|
23
|
+
locale.peek(@env.namespace)
|
24
|
+
}.flatten.uniq.each do |option|
|
25
|
+
print "#{option} "
|
26
|
+
end
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
#######
|
31
|
+
private
|
32
|
+
#######
|
33
|
+
|
34
|
+
# Public: Returns an Array with the locales of the environment.
|
35
|
+
def locales
|
36
|
+
@env.locales
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Mayl
|
2
|
+
module Commands
|
3
|
+
# Public: The Set command accepts a key and asks the user to type in the
|
4
|
+
# translations for that key in each of the locales.
|
5
|
+
#
|
6
|
+
# Example
|
7
|
+
#
|
8
|
+
# command = Set.new(env, 'activerecord.models.post')
|
9
|
+
# command.execute
|
10
|
+
# ca: <type something>
|
11
|
+
# en: <type something>
|
12
|
+
# # Now locales have those values set.
|
13
|
+
#
|
14
|
+
class Set
|
15
|
+
attr_reader :key
|
16
|
+
|
17
|
+
# Public: Initializes a new Set command.
|
18
|
+
#
|
19
|
+
# env - the global environment
|
20
|
+
# key - the String key to be set
|
21
|
+
def initialize(env, key)
|
22
|
+
@env = env
|
23
|
+
@key = key
|
24
|
+
end
|
25
|
+
|
26
|
+
# Public: Executes the command, iterating over each locale, asking the
|
27
|
+
# user for a value, and setting it.
|
28
|
+
#
|
29
|
+
# Returns the key.
|
30
|
+
def execute
|
31
|
+
locales.each do |locale|
|
32
|
+
print " #{locale.to_s}: "
|
33
|
+
locale.set qualified_key, gets.chomp
|
34
|
+
end
|
35
|
+
@key
|
36
|
+
end
|
37
|
+
|
38
|
+
#######
|
39
|
+
private
|
40
|
+
#######
|
41
|
+
|
42
|
+
# Public: Returns an Array with the locales of the environment.
|
43
|
+
def locales
|
44
|
+
@env.locales
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: Returns the given String key according to the qualified
|
48
|
+
# namespace we are in.
|
49
|
+
def qualified_key
|
50
|
+
[@env.namespace.to_s, @key].reject(&:empty?).compact.join('.')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/mayl/env.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Mayl
|
2
|
+
# Public: Represents the global state with the loaded locales, and has the
|
3
|
+
# ability to save locales to disk.
|
4
|
+
class Env
|
5
|
+
attr_reader :locales
|
6
|
+
attr_accessor :last_value
|
7
|
+
attr_accessor :namespace
|
8
|
+
|
9
|
+
# Public: Initializes a new Env loading the locales from a path.
|
10
|
+
def initialize(path)
|
11
|
+
@locales = Loader.load(path)
|
12
|
+
@last_value = nil
|
13
|
+
@namespace = ""
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Saves any changes to disk.
|
17
|
+
def commit
|
18
|
+
@locales.each(&:commit)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/mayl/loader.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Mayl
|
4
|
+
# Public: This module is responsible for loading YAML files and converting
|
5
|
+
# them to Locale objects.
|
6
|
+
#
|
7
|
+
# Example
|
8
|
+
#
|
9
|
+
# Loader.load('config/locales')
|
10
|
+
# # => [#<Locale:...>, #<Locale:...>]
|
11
|
+
#
|
12
|
+
module Loader
|
13
|
+
# Public: Maps a set of YAML files in a directory to Locale objects, to
|
14
|
+
# work comfortably with them.
|
15
|
+
#
|
16
|
+
# path - The path under which to scan for YAML files.
|
17
|
+
#
|
18
|
+
# Returns an Array of Locale objects.
|
19
|
+
def self.load(path)
|
20
|
+
Dir[File.expand_path(path) << "/*.yml"].map { |filename|
|
21
|
+
Locale.new filename, YAML.load(File.read(filename))
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/mayl/locale.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Mayl
|
4
|
+
# Public: A Locale is the representation of a YAML translation file.
|
5
|
+
#
|
6
|
+
# Example
|
7
|
+
#
|
8
|
+
# locale = Locale.new(:ca, {'ca' => {'activerecord' => ... }})
|
9
|
+
# locale.set('activerecord.models.comment', 'Comentari')
|
10
|
+
# locale.get('activerecord.models.comment')
|
11
|
+
# # => 'Comentari
|
12
|
+
#
|
13
|
+
class Locale
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
# Public: Initializes a new Locale.
|
17
|
+
#
|
18
|
+
# path - the filename path of the YAML file
|
19
|
+
# hash - the Hash outputted by the YAML parser
|
20
|
+
def initialize(path, hash)
|
21
|
+
@path = path
|
22
|
+
@name = path.split('/').last.gsub('.yml','').to_sym
|
23
|
+
@data = hash[name.to_s]
|
24
|
+
@dirty = false
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Sets a key to a given value.
|
28
|
+
#
|
29
|
+
# key - the String key to be set, fully qualified
|
30
|
+
# value - the new value to give to that key
|
31
|
+
#
|
32
|
+
# Returns nothing.
|
33
|
+
def set(key, value)
|
34
|
+
ary = key.split('.')
|
35
|
+
qualifier = ary[0..-2]
|
36
|
+
name = ary.last
|
37
|
+
|
38
|
+
_data = @data
|
39
|
+
qualifier.each do |path|
|
40
|
+
_data = _data[path]
|
41
|
+
end
|
42
|
+
_data[name] = value
|
43
|
+
|
44
|
+
@dirty = true
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: Gets the value for a given key.
|
48
|
+
#
|
49
|
+
# key - the String key to be set, fully qualified
|
50
|
+
#
|
51
|
+
# Returns the String value.
|
52
|
+
def get(key)
|
53
|
+
key.split('.').inject(@data) do |acc, name|
|
54
|
+
acc[name] ||= {}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Returns an Array of nodes inside a key, or nil if the key
|
59
|
+
# represents a leaf.
|
60
|
+
def peek(key)
|
61
|
+
result = get(key)
|
62
|
+
if result.is_a?(Hash)
|
63
|
+
result.keys
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Public: Saves any changes to disk.
|
68
|
+
#
|
69
|
+
# Returns nothing.
|
70
|
+
def commit
|
71
|
+
return false unless @dirty
|
72
|
+
|
73
|
+
File.open(@path, 'w') do |f|
|
74
|
+
f.write YAML.dump({ @name.to_s => @data })
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Public: Returns a String representation of the Locale.
|
79
|
+
def to_s
|
80
|
+
@name
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/mayl/parser.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mayl
|
2
|
+
# Public: The parser interprets commands and executes them.
|
3
|
+
class Parser
|
4
|
+
# Public: initializes a new Parser with an environment.
|
5
|
+
#
|
6
|
+
# env - the global state.
|
7
|
+
def initialize(env)
|
8
|
+
@env = env
|
9
|
+
end
|
10
|
+
|
11
|
+
# Public: Parses a given input and creates a command representation for it.
|
12
|
+
#
|
13
|
+
# Returns a Command.
|
14
|
+
def parse(input)
|
15
|
+
operator, *operands = input.split
|
16
|
+
klass = Commands.const_get(operator.capitalize)
|
17
|
+
klass.new(@env, *Array(operands))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/mayl/repl.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Mayl
|
2
|
+
# Public: The class responsible for reading user input, interpreting it and
|
3
|
+
# executing associated commands.
|
4
|
+
class Repl
|
5
|
+
attr_reader :parser
|
6
|
+
|
7
|
+
# Public: Initializes a new REPL from a given path.
|
8
|
+
#
|
9
|
+
# path - The path to get the locales from (defaults to 'config/locales').
|
10
|
+
def initialize(path)
|
11
|
+
path ||= 'config/locales'
|
12
|
+
@env = Env.new(path)
|
13
|
+
@parser = Parser.new(@env)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Fires up the REPL that parses and executes given commands.
|
17
|
+
#
|
18
|
+
# Returns nothing.
|
19
|
+
def start
|
20
|
+
locales = @env.locales.map(&:name)
|
21
|
+
prompt = "> "
|
22
|
+
puts "Detected locales: #{locales.join(', ')}"
|
23
|
+
while (print prompt; input = 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"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/mayl/version.rb
ADDED
data/mayl.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/mayl/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Josep M. Bach"]
|
6
|
+
gem.email = ["josep.m.bach@gmail.com"]
|
7
|
+
gem.description = %q{A console to create, edit and maintain YAML files in any kind of Ruby projects}
|
8
|
+
gem.summary = %q{A console to create, edit and maintain YAML files in any kind of Ruby projects}
|
9
|
+
gem.homepage = "http://blog.txustice.me/mayl"
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "mayl"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Mayl::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency 'yard'
|
19
|
+
gem.add_development_dependency 'yard-tomdoc'
|
20
|
+
gem.add_development_dependency 'redcarpet'
|
21
|
+
|
22
|
+
gem.add_development_dependency 'minitest'
|
23
|
+
gem.add_development_dependency 'mocha'
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module Mayl
|
6
|
+
module Commands
|
7
|
+
describe Cd do
|
8
|
+
before do
|
9
|
+
@locales = [stub(to_s: 'ca'), stub(to_s: 'en')]
|
10
|
+
@env = OpenStruct.new(locales: @locales, namespace: 'activerecord.models')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'enters a directory' do
|
14
|
+
@command = Cd.new @env, 'post.attributes'
|
15
|
+
@command.execute
|
16
|
+
@env.namespace.must_equal 'activerecord.models.post.attributes'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'goes down one level' do
|
20
|
+
@command = Cd.new @env, '..'
|
21
|
+
@command.execute
|
22
|
+
@env.namespace.must_equal 'activerecord'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'goes to the root level' do
|
26
|
+
@command = Cd.new @env, '.'
|
27
|
+
@command.execute
|
28
|
+
@env.namespace.must_equal ''
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
module Mayl
|
5
|
+
module Commands
|
6
|
+
describe Edit do
|
7
|
+
before do
|
8
|
+
@locales = [stub(name: 'ca'), stub(name: 'en')]
|
9
|
+
@env = stub locales: @locales, namespace: '', last_value: 'activerecord.models.post'
|
10
|
+
@command = Edit.new @env, 'en', 'Entry'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'edits the last key getted or setted' do
|
14
|
+
@locales.last.expects(:set).with('activerecord.models.post', 'Entry')
|
15
|
+
@command.execute
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
module Mayl
|
5
|
+
module Commands
|
6
|
+
describe Get do
|
7
|
+
before do
|
8
|
+
@locales = [stub(to_s: 'ca'), stub(to_s: 'en')]
|
9
|
+
@env = stub locales: @locales, namespace: 'activerecord'
|
10
|
+
@command = Get.new @env, 'models.post'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'shows the user the values for a key in each locale' do
|
14
|
+
@locales.first.expects(:get).with('activerecord.models.post').returns('Article')
|
15
|
+
@locales.last.expects(:get).with('activerecord.models.post').returns('Post')
|
16
|
+
|
17
|
+
@command.expects(:print).with(" ca: Article\n")
|
18
|
+
@command.expects(:print).with(" en: Post\n")
|
19
|
+
|
20
|
+
@command.execute
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
module Mayl
|
5
|
+
module Commands
|
6
|
+
describe Ls do
|
7
|
+
before do
|
8
|
+
@locales = [stub(to_s: 'ca'), stub(to_s: 'en')]
|
9
|
+
@env = stub locales: @locales, namespace: 'activerecord'
|
10
|
+
@command = Ls.new @env
|
11
|
+
end
|
12
|
+
|
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']
|
16
|
+
|
17
|
+
@command.expects(:print).with('models ')
|
18
|
+
@command.expects(:print).with('attributes ')
|
19
|
+
|
20
|
+
@command.execute
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Mayl
|
4
|
+
module Commands
|
5
|
+
describe Set do
|
6
|
+
before do
|
7
|
+
@locales = [stub(to_s: 'ca'), stub(to_s: 'en')]
|
8
|
+
@env = stub locales: @locales, namespace: 'activerecord'
|
9
|
+
@command = Set.new @env, 'models.post'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'lets the user enter a value for the key in each of the locales' do
|
13
|
+
@command.expects(:gets).twice.returns('Article', 'Post') # User interaction
|
14
|
+
|
15
|
+
@locales.first.expects(:set).with('activerecord.models.post', 'Article')
|
16
|
+
@locales.last.expects(:set).with('activerecord.models.post', 'Post')
|
17
|
+
|
18
|
+
@command.execute
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Mayl
|
4
|
+
describe Env do
|
5
|
+
before do
|
6
|
+
@locales = [stub, stub]
|
7
|
+
Loader.expects(:load).with('my/path').returns @locales
|
8
|
+
@env = Mayl::Env.new('my/path')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'is a container for locales' do
|
12
|
+
@env.locales.must_equal @locales
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'commits changes to disk' do
|
16
|
+
@locales.each do |locale|
|
17
|
+
locale.expects(:commit)
|
18
|
+
end
|
19
|
+
|
20
|
+
@env.commit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Mayl
|
4
|
+
describe Locale do
|
5
|
+
before do
|
6
|
+
hash = { 'ca' => { 'activerecord' => { 'models' => { 'post' => 'Article' } } } }
|
7
|
+
@locale = Locale.new('some/ca.yml', hash)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'gets a key' do
|
11
|
+
@locale.get('activerecord.models.post').must_equal 'Article'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'sets and retrieves a given key' do
|
15
|
+
@locale.set('activerecord.models.comment', 'Comentari')
|
16
|
+
@locale.get('activerecord.models.comment').must_equal 'Comentari'
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#commit' do
|
20
|
+
it 'does not commit if there are no changes' do
|
21
|
+
@locale.commit.must_equal false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'saves changes to disk' do
|
26
|
+
@locale.set('activerecord.whatever', 'foo')
|
27
|
+
YAML.expects(:dump).with({
|
28
|
+
'ca' => {
|
29
|
+
'activerecord' => {
|
30
|
+
'models' => {
|
31
|
+
'post' => 'Article'
|
32
|
+
},
|
33
|
+
|
34
|
+
'whatever' => 'foo'
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}).returns dumped_contents = stub
|
38
|
+
|
39
|
+
File.expects(:open).with('some/ca.yml', 'w').yields file = stub
|
40
|
+
file.expects(:write).with dumped_contents
|
41
|
+
|
42
|
+
@locale.commit
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'peeks the contents of a given key' do
|
46
|
+
@locale.peek('activerecord').must_equal ['models']
|
47
|
+
@locale.peek('activerecord.models').must_equal ['post']
|
48
|
+
@locale.peek('activerecord.models.post').must_equal nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
module Mayl
|
5
|
+
describe Parser do
|
6
|
+
before do
|
7
|
+
@env = stub
|
8
|
+
@parser = Parser.new(@env)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'parses commands' do
|
12
|
+
command = @parser.parse "set key"
|
13
|
+
command.must_be_kind_of Commands::Set
|
14
|
+
command.key.must_equal 'key'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Mayl
|
4
|
+
describe Repl do
|
5
|
+
before do
|
6
|
+
@repl = Mayl::Repl.new('some/path.yml')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'parses and executes commands' do
|
10
|
+
@foo = stub
|
11
|
+
@foo.expects(:execute)
|
12
|
+
@baz = stub
|
13
|
+
@baz.expects(:execute)
|
14
|
+
|
15
|
+
@repl.expects(:gets).times(3).returns("foo bar\n", "baz lol\n", nil)
|
16
|
+
|
17
|
+
@repl.parser.expects(:parse).with('foo bar').returns @foo
|
18
|
+
@repl.parser.expects(:parse).with('baz lol').returns @baz
|
19
|
+
|
20
|
+
@repl.start
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
data/test/mayl_test.rb
ADDED
data/test/support/ca.yml
ADDED
data/test/support/en.yml
ADDED
data/test/support/es.yml
ADDED
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mayl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Josep M. Bach
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: yard
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: yard-tomdoc
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: redcarpet
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: minitest
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: mocha
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: A console to create, edit and maintain YAML files in any kind of Ruby
|
95
|
+
projects
|
96
|
+
email:
|
97
|
+
- josep.m.bach@gmail.com
|
98
|
+
executables:
|
99
|
+
- mayl
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- .gitignore
|
104
|
+
- .rvmrc
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- bin/mayl
|
110
|
+
- lib/mayl.rb
|
111
|
+
- lib/mayl/commands.rb
|
112
|
+
- lib/mayl/commands/cd.rb
|
113
|
+
- lib/mayl/commands/edit.rb
|
114
|
+
- lib/mayl/commands/exit.rb
|
115
|
+
- lib/mayl/commands/get.rb
|
116
|
+
- lib/mayl/commands/ls.rb
|
117
|
+
- lib/mayl/commands/set.rb
|
118
|
+
- lib/mayl/env.rb
|
119
|
+
- lib/mayl/loader.rb
|
120
|
+
- lib/mayl/locale.rb
|
121
|
+
- lib/mayl/parser.rb
|
122
|
+
- lib/mayl/repl.rb
|
123
|
+
- lib/mayl/version.rb
|
124
|
+
- mayl.gemspec
|
125
|
+
- test/mayl/commands/cd_test.rb
|
126
|
+
- test/mayl/commands/edit_test.rb
|
127
|
+
- test/mayl/commands/exit_test.rb
|
128
|
+
- test/mayl/commands/get_test.rb
|
129
|
+
- test/mayl/commands/ls_test.rb
|
130
|
+
- test/mayl/commands/set_test.rb
|
131
|
+
- test/mayl/env_test.rb
|
132
|
+
- test/mayl/loader_test.rb
|
133
|
+
- test/mayl/locale_test.rb
|
134
|
+
- test/mayl/parser_test.rb
|
135
|
+
- test/mayl/repl_test.rb
|
136
|
+
- test/mayl_test.rb
|
137
|
+
- test/support/ca.yml
|
138
|
+
- test/support/en.yml
|
139
|
+
- test/support/es.yml
|
140
|
+
- test/test_helper.rb
|
141
|
+
homepage: http://blog.txustice.me/mayl
|
142
|
+
licenses: []
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
149
|
+
requirements:
|
150
|
+
- - ! '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ! '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubyforge_project:
|
161
|
+
rubygems_version: 1.8.21
|
162
|
+
signing_key:
|
163
|
+
specification_version: 3
|
164
|
+
summary: A console to create, edit and maintain YAML files in any kind of Ruby projects
|
165
|
+
test_files:
|
166
|
+
- test/mayl/commands/cd_test.rb
|
167
|
+
- test/mayl/commands/edit_test.rb
|
168
|
+
- test/mayl/commands/exit_test.rb
|
169
|
+
- test/mayl/commands/get_test.rb
|
170
|
+
- test/mayl/commands/ls_test.rb
|
171
|
+
- test/mayl/commands/set_test.rb
|
172
|
+
- test/mayl/env_test.rb
|
173
|
+
- test/mayl/loader_test.rb
|
174
|
+
- test/mayl/locale_test.rb
|
175
|
+
- test/mayl/parser_test.rb
|
176
|
+
- test/mayl/repl_test.rb
|
177
|
+
- test/mayl_test.rb
|
178
|
+
- test/support/ca.yml
|
179
|
+
- test/support/en.yml
|
180
|
+
- test/support/es.yml
|
181
|
+
- test/test_helper.rb
|
182
|
+
has_rdoc:
|