konjac 0.1.3 → 0.1.4

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 CHANGED
@@ -2,4 +2,5 @@
2
2
  .bundle
3
3
  .DS_Store
4
4
  Gemfile.lock
5
+ doc/
5
6
  pkg/*
data/README.md CHANGED
@@ -63,13 +63,15 @@ Use multiple dictionaries:
63
63
 
64
64
  konjac translate financial_report_en.txt into japanese using finance
65
65
 
66
- Extract text from a DOCX document (creates a plain-text `test.tags` file):
66
+ Extract text from a DOCX document (creates a plain-text `test.konjac` file from
67
+ `test.docx`):
67
68
 
68
- konjac extract test.docx
69
+ konjac extract test
69
70
 
70
- Import tags file back into DOCX document:
71
+ Import tags file back into DOCX document (file created is named
72
+ `test_imported.docx`):
71
73
 
72
- konjac import test.docx
74
+ konjac import test
73
75
 
74
76
  Extended Example
75
77
  ----------------
@@ -108,7 +110,7 @@ Extended Example
108
110
  en: ""
109
111
  ja: !ruby/regexp /\s(?=[.,:]|$)/
110
112
 
111
- ~/.konjac/test_en.txt
113
+ ~/.konjac/test_en.txt:
112
114
 
113
115
  I like dogs.
114
116
 
@@ -0,0 +1,20 @@
1
+ module Konjac
2
+ module CLI
3
+ class SubCommand
4
+ attr :name, :aliases, :description
5
+
6
+ def initialize(name, aliases, description, &block)
7
+ @name, @aliases, @description = name, aliases, description
8
+ @block = block
9
+ end
10
+
11
+ def alias_text
12
+ @aliases.join ", "
13
+ end
14
+
15
+ def execute
16
+ @block.call
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,77 @@
1
+ module Konjac
2
+ module CLI
3
+ class SubCommandManager
4
+ def initialize
5
+ @sub_commands ||= []
6
+ end
7
+
8
+ def add(name, aliases, description, &block)
9
+ @sub_commands << SubCommand.new(name, aliases, description, &block)
10
+ end
11
+
12
+ def execute(sub_command)
13
+ sub_command = sub_command.to_sym
14
+
15
+ @sub_commands.each do |sc|
16
+ if sc.name == sub_command || sc.aliases.include?(sub_command)
17
+ sc.execute
18
+ return sc.name
19
+ end
20
+ end
21
+
22
+ return nil
23
+ end
24
+
25
+ def all
26
+ @sub_commands
27
+ end
28
+
29
+ def get_lengths
30
+ @lengths = { :name => 8, :aliases => 7, :description => 11 }
31
+
32
+ @sub_commands.each do |sc|
33
+ if sc.name.length > @lengths[:name]
34
+ @lengths[:name] = sc.name.length
35
+ end
36
+ if sc.alias_text.length > @lengths[:aliases]
37
+ @lengths[:aliases] = sc.alias_text.length
38
+ end
39
+ if sc.description.length > @lengths[:description]
40
+ @lengths[:description] = sc.description.length
41
+ end
42
+ end
43
+ end
44
+
45
+ def to_s
46
+ get_lengths
47
+ text = "\n"
48
+
49
+ header_lines = "%s %s %s\n" % [
50
+ "-" * @lengths[:name],
51
+ "-" * @lengths[:aliases],
52
+ "-" * @lengths[:description]
53
+ ]
54
+
55
+ # Create headers
56
+ text << header_lines
57
+ text << "%s %s %s\n" % [
58
+ "Commands".ljust(@lengths[:name]),
59
+ "Aliases".ljust(@lengths[:aliases]),
60
+ "Description".ljust(@lengths[:description])
61
+ ]
62
+ text << header_lines
63
+
64
+ # Write descriptions of each subcommand
65
+ @sub_commands.each do |sc|
66
+ text << "%s %s %s\n" % [
67
+ sc.name.to_s.ljust(@lengths[:name]),
68
+ sc.alias_text.to_s.ljust(@lengths[:aliases]),
69
+ sc.description.to_s.ljust(@lengths[:description])
70
+ ]
71
+ end
72
+
73
+ text
74
+ end
75
+ end
76
+ end
77
+ end
data/lib/konjac/cli.rb CHANGED
@@ -1,28 +1,43 @@
1
1
  module Konjac
2
2
  module CLI
3
+ autoload :SubCommand, "konjac/cli/sub_command"
4
+ autoload :SubCommandManager, "konjac/cli/sub_command_manager"
5
+
3
6
  class << self
7
+ def init_sub_commands
8
+ @valid_commands = SubCommandManager.new
9
+ @valid_commands.add :extract, [:export, :e, :x], "Extract text from a DOCX file" do
10
+ Word.extract_docx_tags(ARGV)
11
+ end
12
+ @valid_commands.add :help, [:h, :"-h", :"?"], "Show help" do
13
+ show_help
14
+ end
15
+ @valid_commands.add :import, [:i, :m], "Import text back into a DOCX file" do
16
+ Word.import_docx_tags(ARGV)
17
+ end
18
+ @valid_commands.add :translate, [:t], "Translate a file" do
19
+ translate
20
+ end
21
+ end
22
+
4
23
  def start
24
+ init_sub_commands
5
25
  show_help if ARGV.empty?
6
26
 
7
27
  # Subcommand
8
- case ARGV.shift
9
- when "translate"
10
- translate
11
- when "extract", "export"
12
- Word.extract_docx_tags(ARGV)
13
- when "import"
14
- Word.import_docx_tags(ARGV)
15
- when "add"
16
- when "help"
28
+ sub_command = ARGV.shift
29
+ result = @valid_commands.execute(sub_command)
30
+
31
+ if result.nil?
17
32
  show_help
18
- else
19
- raise InvalidCommandError.new("Valid commands are translate or add")
33
+ raise InvalidCommandError.new("Invalid subcommand: #{sub_command}")
20
34
  end
35
+
36
+ result
21
37
  end
22
38
 
23
39
  def show_help
24
- puts "Help"
25
- exit 0
40
+ puts @valid_commands.to_s
26
41
  end
27
42
 
28
43
  private
@@ -16,14 +16,13 @@ module Konjac
16
16
  from_lang = from_lang.to_s
17
17
  to_lang = to_lang.to_s
18
18
 
19
+ # Ignore everything if we've been here before
20
+ return @pairs if loaded?(from_lang, to_lang, dictionaries) || opts[:force]
21
+
19
22
  # Build a regex template for the from language
20
23
  from_template = build_regex_template(from_lang)
21
24
  to_template = build_replacement_template(from_lang, to_lang)
22
25
 
23
- # Get full path from name
24
-
25
- return @pairs if loaded?(from_lang, to_lang, dictionaries) || opts[:force]
26
-
27
26
  # Save variables to cache so we can avoid repetitive requests
28
27
  cache_load from_lang, to_lang, dictionaries
29
28
 
@@ -46,40 +45,51 @@ module Konjac
46
45
  # Build a list of search and replace pairs
47
46
  @pairs = []
48
47
  @dictionary.each do |term|
49
- if term.has_key?(to_lang)
50
- # Build to term depending on whether it's a hash for complex
51
- # matches or a simple string
52
- if term[to_lang].is_a?(Hash)
53
- to_term = term[to_lang][to_lang]
54
-
55
- if term[to_lang].has_key?(from_lang)
56
- from_term = term[to_lang][from_lang]
57
- end
58
- else
59
- to_term = term[to_lang]
60
- end
48
+ pair = extract_pair_from_term(term, from_lang, to_lang, from_template, to_template)
49
+ @pairs << pair unless pair.nil?
50
+ end
61
51
 
62
- # Build from term if it doesn't already exist
63
- if term.has_key?(from_lang) && from_term.nil?
64
- from_term = term[from_lang]
65
- end
52
+ @pairs
53
+ end
66
54
 
67
- unless from_term.nil?
68
- # Build a regular expression if it isn't already one
69
- # Note that this will apply word boundary rules, so to avoid them
70
- # create a regular expression in the dictionary file
71
- unless from_term.is_a?(Regexp)
72
- from_term = Regexp.new(from_template % from_term)
73
- end
55
+ def extract_pair_from_term(term, from_lang, to_lang, from_template, to_template)
56
+ if term.has_key?(to_lang)
57
+ # Build to term depending on whether it's a hash for complex
58
+ # matches or a simple string
59
+ if term[to_lang].is_a?(Hash)
60
+ to_term = term[to_lang][to_lang]
74
61
 
75
- to_term = to_template % to_term unless to_term =~ BLANK
62
+ if term[to_lang].has_key?(from_lang)
63
+ from_term = term[to_lang][from_lang]
64
+ end
65
+ else
66
+ to_term = term[to_lang]
67
+ end
76
68
 
77
- @pairs << [ from_term, to_term ]
69
+ # Build from term if it doesn't already exist
70
+ if term.has_key?(from_lang) && from_term.nil?
71
+ from_term = term[from_lang]
72
+ end
73
+
74
+ unless from_term.nil?
75
+ # Build a regular expression if it isn't already one.
76
+ # Note that this will apply word boundary rules, so to avoid them
77
+ # create a regular expression in the dictionary file.
78
+ # Matching is case-insensitive unless the expression contains a
79
+ # capital letter.
80
+ unless from_term.is_a?(Regexp)
81
+ from_term = Regexp.new(from_template % from_term,
82
+ ("i" unless from_term =~ /[A-Z]/))
78
83
  end
84
+
85
+ to_term = to_template % to_term unless to_term =~ BLANK
86
+
87
+ return [ from_term, to_term ]
79
88
  end
80
89
  end
81
90
 
82
- @pairs
91
+ # Return nil if no term could be constructed
92
+ return nil
83
93
  end
84
94
 
85
95
  # Verifies whether the dictionary exists on the specified path, creating
@@ -1,3 +1,3 @@
1
1
  module Konjac
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
data/spec/cli_spec.rb CHANGED
@@ -3,8 +3,15 @@ require File.dirname(__FILE__) + "/spec_helper"
3
3
  require "tempfile"
4
4
 
5
5
  describe CLI do
6
+ # Super hacky way of setting a constant without setting off a warnings that the
7
+ # constant has already been initialized
8
+ def set_argv(*params)
9
+ Object.__send__ :remove_const, :ARGV
10
+ Object.const_set :ARGV, params
11
+ end
12
+
6
13
  it "should fail on an invalid subcommand" do
7
- ARGV = ["invalid"]
14
+ set_argv "invalid"
8
15
  lambda { CLI.start }.should raise_error InvalidCommandError
9
16
  end
10
17
 
@@ -14,8 +21,8 @@ describe CLI do
14
21
  @dictionary = Tempfile.new(["dict", ".yml"])
15
22
  @dictionary.write <<-eos
16
23
  -
17
- en: dogs
18
- ja: 犬
24
+ en: dogs
25
+ ja: 犬
19
26
  eos
20
27
  @dictionary.rewind
21
28
 
@@ -23,14 +30,17 @@ describe CLI do
23
30
  @english = Tempfile.new(["english", "_en.txt"])
24
31
  @english.write "I like dogs."
25
32
  @english.rewind
33
+
34
+ # Set ARGV
35
+ set_argv "translate", @english.path, "into", "japanese", "using",
36
+ @dictionary.path
26
37
  end
27
38
 
28
39
  it "should correctly translate English text" do
29
40
  begin
30
- ARGV = ["translate", @english.path, "into", "japanese", "using", @dictionary.path]
31
41
  CLI.start
32
42
  converted_path = Utils.build_converted_file_name(@english.path, "en", "ja")
33
- puts File.read(@english.path).should == "I like dogs."
43
+ File.read(@english.path).should == "I like dogs."
34
44
  File.read(converted_path).should == "I like 犬.\n"
35
45
  ensure
36
46
  @dictionary.close!
@@ -38,5 +48,9 @@ describe CLI do
38
48
  File.delete converted_path
39
49
  end
40
50
  end
51
+
52
+ it "should return the name of the sub_command" do
53
+ CLI.start.should == :translate
54
+ end
41
55
  end
42
56
  end
@@ -7,14 +7,82 @@ describe Dictionary do
7
7
  @dictionary = Tempfile.new(["dict", ".yml"])
8
8
  @dictionary.write <<-eos
9
9
  -
10
- en: dogs
11
- ja: 犬
10
+ en: dogs
11
+ ja: 犬
12
+ -
13
+ en: cat
14
+ ja:
15
+ ja: 猫
16
+ en: cats?
17
+ -
18
+ ja:
19
+ ja: 。
20
+ en: !ruby/regexp /\\.\\s?/
21
+ -
22
+ en: mouth
23
+ es: boca
24
+ -
25
+ es: mano
26
+ ja: 手
27
+ -
28
+ en:
29
+ en: book
30
+ ja: 本
31
+ -
32
+ en: North Carolina
33
+ ja: ノースカロライナ
12
34
  eos
13
35
  @dictionary.rewind
14
36
  end
15
37
 
16
- it "should correctly load YAML" do
17
- Dictionary.load "en", "ja", [@dictionary.path]
18
- Dictionary.pairs.should == [[/\bdogs\b/, ""]]
38
+ describe "when converting from English to Japanese" do
39
+ before :each do
40
+ Dictionary.load "en", "ja", [@dictionary.path]
41
+ end
42
+
43
+ it "should correctly load a simple term" do
44
+ Dictionary.pairs.first.should == [/\bdogs\b/i, "犬"]
45
+ end
46
+
47
+ it "should correctly load a slightly more complex regular expression" do
48
+ Dictionary.pairs[1].should == [/\bcats?\b/i, "猫"]
49
+ end
50
+
51
+ it "should correctly load a manual regular expression" do
52
+ Dictionary.pairs[2].should == [/\.\s?/, "。"]
53
+ end
54
+
55
+ it "should ignore examples for which the source language cannot be found" do
56
+ Dictionary.pairs.keep_if { |t| t[0] == /\bmano\b/i }.empty?.should == true
57
+ end
58
+
59
+ it "should ignore examples for which the target language cannot be found" do
60
+ Dictionary.pairs.keep_if { |t| t[1] == "book" }.empty?.should == true
61
+ end
62
+
63
+ it "should only have a case-insensitive search if the search contains capital letters" do
64
+ Dictionary.pairs[0][0].should == /\bdogs\b/i
65
+ Dictionary.pairs[3][0].should == /\bNorth Carolina\b/
66
+ end
67
+ end
68
+
69
+ describe "when converting from Japanese to English" do
70
+ before :each do
71
+ Dictionary.load "ja", "en", [@dictionary.path]
72
+ end
73
+
74
+ it "should add whitespace to term replacement" do
75
+ Dictionary.pairs.first.should == [/犬/i, "dogs "]
76
+ end
77
+ end
78
+
79
+ describe "when converting from English to Spanish" do
80
+ before :each do
81
+ Dictionary.load "en", "es", [@dictionary.path]
82
+ end
83
+
84
+ it "should not add whitespace to term replacement" do
85
+ Dictionary.pairs[0].should == [/\bmouth\b/i, "boca"]
86
+ end
19
87
  end
20
88
  end
@@ -11,6 +11,10 @@ describe Language do
11
11
  Language.find(:jpn).should == :ja
12
12
  end
13
13
 
14
+ it "should fail to find a made-up language" do
15
+ lambda { Language.find(:black_speech) }.should raise_error InvalidLanguageError
16
+ end
17
+
14
18
  it "should return equal results for both strings and symbols" do
15
19
  Language.find(:english).should == Language.find("english")
16
20
  end
data/spec/tag_spec.rb CHANGED
@@ -6,15 +6,18 @@ describe Tag do
6
6
  before :each do
7
7
  @tags_file = Tempfile.new(["tags", ".tags"])
8
8
  @tags_file.write <<-eos.gsub(/^\s+/, "")
9
- [[KJ-1]]
9
+ [[KJ-0]]
10
10
  > 犬
11
11
  dog
12
- [[KJ-2]]
12
+ [[KJ-1]]
13
13
  > 何ですか。
14
14
  What is it?
15
- [[KJ-3]]
15
+ [[KJ-2]]
16
16
  > 空白
17
- [[KJ-6]]
17
+ [[KJ-3]] #=> comment
18
+ > コメント
19
+ Comment
20
+ [[KJ-5]]
18
21
  > 以上
19
22
  -- end --
20
23
  eos
@@ -22,26 +25,37 @@ describe Tag do
22
25
  @manager = TagManager.new(@tags_file.path)
23
26
  end
24
27
 
25
- it "should accurately read a tag file" do
28
+ it "should accurately read a tag" do
26
29
  @manager.all.should_not == nil
27
- @manager[0].index.should == 1
30
+ @manager[0].index.should == 0
28
31
  @manager[0].original.should == "犬"
29
32
  @manager[0].translated.should == "dog"
30
33
  end
31
34
 
32
- it "should succeed reading multiple lines" do
33
- @manager[1].index.should == 2
35
+ it "should succeed reading multiple tags" do
36
+ @manager[1].index.should == 1
34
37
  @manager[1].original.should == "何ですか。"
35
38
  @manager[1].translated.should == "What is it?"
36
39
  end
37
40
 
38
41
  it "should ignore blank translations" do
39
- @manager[2].index.should == 3
42
+ @manager[2].index.should == 2
40
43
  @manager[2].original.should == "空白"
41
44
  @manager[2].translated.should == nil
42
45
  end
43
46
 
47
+ it "should know whether a tag has been translated" do
48
+ @manager[0].translated?.should == true
49
+ @manager[2].translated?.should == false
50
+ end
51
+
52
+ it "should ignore comments and additional info after an index tag" do
53
+ @manager[3].index.should == 3
54
+ @manager[3].original.should == "コメント"
55
+ @manager[3].translated.should == "Comment"
56
+ end
57
+
44
58
  it "should skip over blank indexes" do
45
- @manager[3].index.should == 6
59
+ @manager[4].index.should == 5
46
60
  end
47
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: konjac
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-01-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &70101148958680 !ruby/object:Gem::Requirement
16
+ requirement: &70265140795800 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70101148958680
24
+ version_requirements: *70265140795800
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70101148958040 !ruby/object:Gem::Requirement
27
+ requirement: &70265140794440 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70101148958040
35
+ version_requirements: *70265140794440
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70101148683020 !ruby/object:Gem::Requirement
38
+ requirement: &70265140793660 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70101148683020
46
+ version_requirements: *70265140793660
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sdoc
49
- requirement: &70101148682400 !ruby/object:Gem::Requirement
49
+ requirement: &70265140792780 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70101148682400
57
+ version_requirements: *70265140792780
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: autotest
60
- requirement: &70101148681900 !ruby/object:Gem::Requirement
60
+ requirement: &70265140791700 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70101148681900
68
+ version_requirements: *70265140791700
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: autotest-fsevent
71
- requirement: &70101148681460 !ruby/object:Gem::Requirement
71
+ requirement: &70265140790860 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70101148681460
79
+ version_requirements: *70265140790860
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: autotest-growl
82
- requirement: &70101148681040 !ruby/object:Gem::Requirement
82
+ requirement: &70265140789760 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70101148681040
90
+ version_requirements: *70265140789760
91
91
  description: A Ruby command-line utility for translating files using a YAML wordlist
92
92
  email:
93
93
  - bryan.mckelvey@gmail.com
@@ -107,6 +107,8 @@ files:
107
107
  - konjac.gemspec
108
108
  - lib/konjac.rb
109
109
  - lib/konjac/cli.rb
110
+ - lib/konjac/cli/sub_command.rb
111
+ - lib/konjac/cli/sub_command_manager.rb
110
112
  - lib/konjac/dictionary.rb
111
113
  - lib/konjac/exception.rb
112
114
  - lib/konjac/language.rb