yamlt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 31ebdd1c019feb3155c4ea520ec2c81c6f7fc0a0
4
+ data.tar.gz: 51d7d3b140f9394a13786e6fda384181d268877d
5
+ SHA512:
6
+ metadata.gz: bbe927ff3463528669f4f6d57c4fd3bf6f66a37bde301b902079410d3d77c08f6e6b78fbfce3f924d229b71c1ef34df715fc95bd38e31149bdafe647a472323f
7
+ data.tar.gz: f074c43f9fbf5c9b0a60a290a91a4c995a99bf46afb5d9918a1dfc094c3ce0fd9184da2eccb4b38019cfa6d01e888f3008aafd4850a4117e548aae382048ece3
@@ -0,0 +1,33 @@
1
+ # ------------------------------------------------------------------------------
2
+ # @class: Yamlt::Checker::Reporter
3
+ # @description: Default checker reporter
4
+ # ------------------------------------------------------------------------------
5
+
6
+ module Yamlt
7
+ class Checker
8
+ class Reporter
9
+ def absent(key, old_value)
10
+ print " * Key is absent: #{key}, old_value: "
11
+ puts_value(old_value)
12
+ end
13
+
14
+ def unchanged(key, old_value)
15
+ puts " * Key is unchanged: #{key}, old_value: "
16
+ puts_value(old_value)
17
+ end
18
+
19
+ private
20
+
21
+ def puts_value(value)
22
+ if value.include?($/)
23
+ lines = value.split($/)
24
+ max_length = lines.map(&:length).max
25
+ puts $/ + value.split($/).map{|s|" | #{s}"} * $/
26
+ puts " `-" + "-" * max_length
27
+ else
28
+ puts value
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,58 @@
1
+ # ------------------------------------------------------------------------------
2
+ # @class: Yamlt::Checker
3
+ # @description: Makes a diff between two yaml files
4
+ # ------------------------------------------------------------------------------
5
+ require "yamlt/parser"
6
+ require "yamlt/loader"
7
+ require "yamlt/checker/reporter"
8
+
9
+ module Yamlt
10
+ class Checker
11
+ def initialize(source, target, reporter = Yamlt::Checker::Reporter.new)
12
+ @source = source
13
+ @target = target
14
+ @reporter = reporter
15
+ end
16
+
17
+ def call
18
+ check
19
+ end
20
+
21
+ def self.call(source, target, reporter)
22
+ new(source, target, reporter).()
23
+ end
24
+
25
+ private
26
+
27
+ def state
28
+ @state ||=
29
+ if @source.is_a?(String)
30
+ Yamlt::Parser.new(@source).parse
31
+ else
32
+ @source
33
+ end
34
+ end
35
+
36
+ def loader
37
+ @loader ||=
38
+ if @target.is_a?(String)
39
+ Yamlt::Loader.new(@target)
40
+ else
41
+ @target
42
+ end
43
+ end
44
+
45
+ def check
46
+ state.values.keys.each do |key|
47
+ source_value = state.values[key]
48
+ target_value = loader[key]
49
+
50
+ if target_value.nil?
51
+ @reporter.absent(key, source_value)
52
+ elsif target_value == source_value
53
+ @reporter.unchanged(key, source_value)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,15 @@
1
+ #
2
+ #
3
+ #
4
+ #
5
+
6
+ module Yamlt
7
+ class LanguagePair
8
+ def initialize(from: "en", to: "ru")
9
+ @from = from
10
+ @to = to
11
+ end
12
+
13
+ attr_reader :from, :to
14
+ end
15
+ end
@@ -0,0 +1,61 @@
1
+ #
2
+ #
3
+ #
4
+ #
5
+ #
6
+ require "yaml"
7
+
8
+ module Yamlt
9
+ class Loader
10
+ def initialize(filepath)
11
+ @filepath = filepath
12
+ @loaded = false
13
+ end
14
+
15
+ def [](key)
16
+ path = path0(key)
17
+ value = values
18
+ path.each do |fragment|
19
+ value = value[fragment]
20
+ return nil unless value
21
+ end
22
+ value
23
+ end
24
+
25
+ def language
26
+ @locale ||=
27
+ begin
28
+ values.keys.first || @filepath[/(\w+)\.yml$/, 1]
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def path0(key)
35
+ keys = values.keys
36
+
37
+ raise Yamlt::LoaderException "Locale file should have only one root key" if keys.size != 1
38
+
39
+ key.split(".").tap do |path|
40
+ path[0] = keys.first
41
+ end
42
+ end
43
+
44
+ def values
45
+ @values ||= (load unless @loaded)
46
+ end
47
+
48
+ def load
49
+ begin
50
+ @values = YAML.load_file(@filepath)
51
+ rescue Errno::ENOENT => noent
52
+ @values = {}
53
+ end
54
+
55
+ @loaded = true
56
+ @values
57
+ end
58
+ end
59
+
60
+ class LoaderException < ::StandardError; end
61
+ end
@@ -0,0 +1,74 @@
1
+ module Yamlt
2
+ class Parser
3
+ class Line
4
+ class Serializer
5
+ def initialize(line, overrides = {})
6
+ @line = line
7
+ @overrides = overrides
8
+ end
9
+
10
+ def to_s
11
+ [ level_string,
12
+ fragment_string,
13
+ prefix_string,
14
+ value_string,
15
+ comment
16
+ ].join("")
17
+ end
18
+
19
+ private
20
+
21
+ def level_string
22
+ if @line.level
23
+ indent(@line.level)
24
+ end.to_s
25
+ end
26
+
27
+ def indent(lvl)
28
+ " " * lvl
29
+ end
30
+
31
+ def fragment_string
32
+ if fragment
33
+ "#{fragment}:"
34
+ end.to_s
35
+ end
36
+
37
+ def fragment
38
+ @overrides[:fragment] || @line.fragment
39
+ end
40
+
41
+ def comment
42
+ if @line.comment
43
+ "##{@line.comment}"
44
+ end.to_s
45
+ end
46
+
47
+ def prefix_string
48
+ @line.prefix.to_s
49
+ end
50
+
51
+ def value_string
52
+ if @line.fragment && value
53
+ if value.include?($/)
54
+ "|\n" +
55
+ value.split($/).map do |value_part|
56
+ "#{indent(@line.level + 1)}\"#{escaped(value_part)}\""
57
+ end.join($/)
58
+ else
59
+ "\"#{escaped(value)}\""
60
+ end
61
+ end.to_s
62
+ end
63
+
64
+ def value
65
+ @overrides[:value] || @line.value
66
+ end
67
+
68
+ def escaped(string)
69
+ string.gsub(/\"/, "\\\"")
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,67 @@
1
+ #
2
+ #
3
+ #
4
+ #
5
+ #
6
+ require "yamlt/parser/line/serializer"
7
+
8
+ module Yamlt
9
+ class Parser
10
+ class Line
11
+ def initialize(text)
12
+ @text = text
13
+ parse
14
+ end
15
+
16
+ attr_reader :comment, :prefix, :fragment, :level, :multiline
17
+ attr_accessor :full_path, :value
18
+
19
+ def as_text(opts={})
20
+ serializer = Serializer.new(self, opts)
21
+ serializer.to_s
22
+ end
23
+
24
+ def empty?
25
+ !@fragment && !@value
26
+ end
27
+
28
+ private
29
+
30
+ def parse
31
+ case @text
32
+ when /^\s*$/
33
+ # do nothing
34
+ when /^(\s*)#(.*)$/; @comment = $~[2]; @prefix = $~[1]
35
+ when /^(\s*)(\w+):(\s*)(#(.*))?$/
36
+ if $~[1].length % 2 == 0
37
+ @fragment = $~[2]
38
+ @level = $~[1].length / 2
39
+ @prefix = $~[3]
40
+ @comment = $~[5]
41
+ end
42
+ when /^(\s*)(\w+):(\s*)([\'\"])(.*)\4/
43
+ if $~[1].length % 2 == 0
44
+ @fragment = $~[2]
45
+ @level = $~[1].length / 2
46
+ @prefix = $~[3]
47
+ @value = $~[5]
48
+ end
49
+ when /^(\s*)(\w+):(\s*)\|(\s*)$/
50
+ if $~[1].length % 2 == 0
51
+ @fragment = $~[2]
52
+ @level = $~[1].length / 2
53
+ @prefix = $~[3] || $~[4]
54
+ @multiline = true
55
+ end
56
+
57
+ when /^(\s*)([\'\"]?)(.*)\2\s*$/
58
+ if $~[1].length % 2 == 0
59
+ @level = $~[1].length / 2
60
+ @value = $~[3]
61
+ @multiline = true
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,87 @@
1
+ module Yamlt
2
+ class Parser
3
+ class State
4
+ def initialize
5
+ @path = []
6
+ @level = 0
7
+ @multiline = []
8
+ @line = nil
9
+
10
+ @lines = []
11
+ @values = {}
12
+
13
+ @languate = nil
14
+ end
15
+
16
+ attr_reader :path, :level, :multiline, :line, :lines, :values, :language
17
+
18
+ def apply(line)
19
+ pass_through(line) if line.empty?
20
+ apply_fragment(line) if line.fragment
21
+ apply_value(line) if !line.fragment && line.value
22
+ end
23
+
24
+ def flush
25
+ if @line && @line.multiline && !@multiline.empty?
26
+ add_value
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def pass_through(line)
33
+ @lines.push(line)
34
+ end
35
+
36
+ def apply_fragment(line)
37
+ if line.level > @level
38
+ raise StateException, "Path fragment level is too high\n#{line.as_text}"
39
+ elsif line.level < @level
40
+ if !@multiline.empty? && @line
41
+ add_value
42
+ end
43
+ end
44
+
45
+ if line.level == 0 && line.fragment
46
+ @language ||= line.fragment
47
+ end
48
+
49
+ @path = @path[0, line.level]
50
+ @path.push(line.fragment)
51
+ @level = line.level + 1
52
+
53
+ @lines.push(line)
54
+
55
+ if line.value
56
+ full_path = @path.join(".")
57
+ line.full_path = full_path
58
+ @values[full_path] = line.value
59
+ end
60
+
61
+ if line.multiline
62
+ @line = line
63
+ @multiline = []
64
+ end
65
+ end
66
+
67
+ def apply_value(line)
68
+ if line.level != @level
69
+ raise Yamlt::Parser::StateException, "Wrong identation in multiline value\n#{line.as_text}"
70
+ end
71
+ @multiline.push(line.value)
72
+ end
73
+
74
+ def add_value
75
+ full_path = @path.join(".")
76
+ value = @multiline.join($/)
77
+ @values[full_path] = value
78
+ @line.full_path = full_path
79
+ @line.value = value
80
+ @multiline = []
81
+ @line = nil
82
+ end
83
+ end
84
+
85
+ class StateException < ::StandardError; end
86
+ end
87
+ end
@@ -0,0 +1,38 @@
1
+ # ------------------------------------------------------------------------------
2
+ # @class: Yamlt::Parser
3
+ # @description: Parse yaml file structure and store it into state object
4
+ # ------------------------------------------------------------------------------
5
+ require "yamlt/parser/line"
6
+ require "yamlt/parser/state"
7
+
8
+ module Yamlt
9
+ #
10
+ #
11
+ class Parser
12
+ #
13
+ #
14
+ #
15
+ def initialize(filepath)
16
+ @filepath = filepath
17
+ @state = Yamlt::Parser::State.new
18
+ end
19
+
20
+ #
21
+ #
22
+ def parse
23
+ IO.read(@filepath).each_line do |line|
24
+ parse_line(line)
25
+ end
26
+
27
+ @state.flush
28
+
29
+ @state
30
+ end
31
+
32
+ private
33
+
34
+ def parse_line(text)
35
+ @state.apply(Yamlt::Parser::Line.new(text))
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ # ------------------------------------------------------------------------------
2
+ # @class: Yamlt::Translator
3
+ # @description: Default class for translating from lang1 to lang2
4
+ # ------------------------------------------------------------------------------
5
+
6
+ module Yamlt
7
+ class Translator
8
+ def initialize(source_lang, target_lang)
9
+ @source_lang = source_lang
10
+ @target_lang = target_lang
11
+ end
12
+
13
+ def translate(original,target = nil)
14
+ if respond_to?(:custom_translate)
15
+ self.custom_translate(original, target)
16
+ else
17
+ original
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ # ------------------------------------------------------------------------------
2
+ # @class: Yamlt::Updater
3
+ # @description: Takes first yaml file as template and writes second file copy
4
+ # ------------------------------------------------------------------------------
5
+
6
+ require "yamlt/loader"
7
+ require "yamlt/parser"
8
+ require "yamlt/translator"
9
+
10
+ module Yamlt
11
+ class Updater
12
+ def initialize(source, target, translator_class = Yamlt::Translator)
13
+ @source = source
14
+ @target = target
15
+ @translator = translator_class.new(state.language, loader.language)
16
+ end
17
+
18
+ def call
19
+ of = File.new(target_updated, "w")
20
+
21
+ state.lines.each do |line|
22
+ of.puts format_line(line)
23
+ end
24
+
25
+ of.close
26
+ end
27
+
28
+ def rename_updated
29
+ File.rename(target_updated, target)
30
+ end
31
+
32
+ private
33
+
34
+ def state
35
+ @state ||=
36
+ if @source.is_a?(String)
37
+ Yamlt::Parser.new(@source).parse
38
+ else
39
+ @source
40
+ end
41
+ end
42
+
43
+ def loader
44
+ @loader ||= Yamlt::Loader.new(@target)
45
+ end
46
+
47
+ def target_updated
48
+ @target_updated ||=
49
+ if /\.yml$/ === @target
50
+ @target[/^(.*)\.yml$/, 1] + ".updated.yml"
51
+ else
52
+ @target + ".updated.yml"
53
+ end
54
+ end
55
+
56
+ def format_line(line)
57
+ if line.level == 0 && line.fragment
58
+ line.as_text(fragment: loader.language)
59
+ else
60
+ line.as_text
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,56 @@
1
+ #
2
+ #
3
+ #
4
+ #
5
+ #
6
+ module Yamlt
7
+ class Writer
8
+ def initialize(state, loader,
9
+ opts = {from: "en", to: "ru"},
10
+ callback = -> (old_value, path, from_l, to_l) { old_value } )
11
+ @state = state
12
+ @loader = loader
13
+ @opts = opts
14
+ @callback = callback
15
+ end
16
+
17
+ def write(stream)
18
+ @state.lines.each do |line|
19
+ unless line.value
20
+ stream.write(line.as_text)
21
+ else
22
+ stream.write(format_line(line))
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def value_by_path(path)
30
+ value = @loader[path]
31
+
32
+ raise Yamlt::WriterException unless [String, NilClass].include?(value.class)
33
+
34
+ value
35
+ end
36
+
37
+ def format_line(line)
38
+ old_value = value_by_path(line.full_path) || line.value
39
+
40
+ new_value = @callback.(old_value, line.full_path, @opts[:from], @opts[:to])
41
+
42
+ multiline = new_value.to_s.split($/)
43
+
44
+ if multiline.size > 1
45
+ ([ " " * line.level + line.fragment + ": |" ] +
46
+ multiline.map { |str| " " * (line.level + 1) + str }) * $/
47
+ else
48
+ " " * line.level + line.fragment + ": " + escaped_value(new_value)
49
+ end
50
+ end
51
+
52
+ def escaped_value(value)
53
+ "\"" + value.gsub("\"", "\\\"") + "\""
54
+ end
55
+ end
56
+ end
data/lib/yamlt.rb ADDED
@@ -0,0 +1,8 @@
1
+ #
2
+ #
3
+ #
4
+ #
5
+ #
6
+ require "yamlt/parser"
7
+ require "yamlt/loader"
8
+ require "yamlt/checker"
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yamlt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tangerine Cat
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Take yaml structure from locale file and apply to another one
28
+ email: kaineer@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/yamlt.rb
34
+ - lib/yamlt/checker.rb
35
+ - lib/yamlt/checker/reporter.rb
36
+ - lib/yamlt/language_pair.rb
37
+ - lib/yamlt/loader.rb
38
+ - lib/yamlt/parser.rb
39
+ - lib/yamlt/parser/line.rb
40
+ - lib/yamlt/parser/line/serializer.rb
41
+ - lib/yamlt/parser/state.rb
42
+ - lib/yamlt/translator.rb
43
+ - lib/yamlt/updater.rb
44
+ - lib/yamlt/writer.rb
45
+ homepage: http://rubygems.org/gems/yamlt
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 2.2.2
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Take yaml structure from locale file and apply to another one
69
+ test_files: []