rescodegen 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +21 -1
- data/README.md +47 -17
- data/Rakefile +10 -1
- data/bin/rescodegen +49 -15
- data/lib/rescodegen/code_generator/objc_header_strings_generator.rb +34 -14
- data/lib/rescodegen/code_generator/objc_main_strings_generator.rb +93 -65
- data/lib/rescodegen/code_generator/strings_generator.rb +3 -4
- data/lib/rescodegen/code_generator/swift_strings_generator.rb +45 -16
- data/lib/rescodegen/key_generator/code_safe_key_generator.rb +44 -0
- data/lib/rescodegen/key_generator/key_generator.rb +24 -0
- data/lib/rescodegen/key_reader/strings_key_reader.rb +27 -0
- data/lib/rescodegen/key_reader/stringsdict_key_reader.rb +13 -0
- data/lib/rescodegen/version.rb +1 -1
- data/rescodegen.gemspec +4 -0
- metadata +48 -3
- data/lib/rescodegen/key_generator/strings_key_generator.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c59f55dbbfbcb78c9f1d27bc7d15d0dea733865c
|
4
|
+
data.tar.gz: a0b55eef2c05a946010250bcc67bb696bb30fe9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61fb365a48ad5132662a7c82512691d453e36f64160f0279a834a3b8654055f53064f875ec00692ab13e58a0acdb1003c8372c1880a4198ac4e58ffa38527b7a
|
7
|
+
data.tar.gz: 7082b4311ae00f35d82d223d37b3c02b27cd1ece9375c82500c556c01e63bb1a2b0fe26e7ebfd941408efeac1c6e00d1386e6df44494fa858bdd4d4583aff0d2
|
data/Gemfile.lock
CHANGED
@@ -1,15 +1,33 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rescodegen (0.
|
4
|
+
rescodegen (0.2.0)
|
5
|
+
plist (= 3.2.0)
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
10
|
+
codeclimate-test-reporter (0.5.0)
|
11
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
12
|
+
diff-lcs (1.2.5)
|
9
13
|
docile (1.1.5)
|
10
14
|
json (1.8.3)
|
11
15
|
minitest (5.8.4)
|
16
|
+
plist (3.2.0)
|
12
17
|
rake (10.5.0)
|
18
|
+
rspec (3.4.0)
|
19
|
+
rspec-core (~> 3.4.0)
|
20
|
+
rspec-expectations (~> 3.4.0)
|
21
|
+
rspec-mocks (~> 3.4.0)
|
22
|
+
rspec-core (3.4.3)
|
23
|
+
rspec-support (~> 3.4.0)
|
24
|
+
rspec-expectations (3.4.0)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.4.0)
|
27
|
+
rspec-mocks (3.4.1)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.4.0)
|
30
|
+
rspec-support (3.4.1)
|
13
31
|
simplecov (0.11.2)
|
14
32
|
docile (~> 1.1.0)
|
15
33
|
json (~> 1.8)
|
@@ -21,9 +39,11 @@ PLATFORMS
|
|
21
39
|
|
22
40
|
DEPENDENCIES
|
23
41
|
bundler (~> 1.11)
|
42
|
+
codeclimate-test-reporter (~> 0.5)
|
24
43
|
minitest (~> 5.0)
|
25
44
|
rake (~> 10.0)
|
26
45
|
rescodegen!
|
46
|
+
rspec (~> 3.4)
|
27
47
|
simplecov (~> 0.11)
|
28
48
|
|
29
49
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -1,39 +1,69 @@
|
|
1
|
+
<a href="https://codeclimate.com/github/seanhenry/rescodegen/coverage"><img src="https://codeclimate.com/github/seanhenry/rescodegen/badges/coverage.svg" /></a>
|
2
|
+
<a href="https://codeclimate.com/github/seanhenry/rescodegen"><img src="https://codeclimate.com/github/seanhenry/rescodegen/badges/gpa.svg" /></a>
|
1
3
|
# rescodegen
|
2
|
-
A command line tool for creating Swift and Objective-C code from
|
4
|
+
A command line tool for creating Swift and Objective-C code from singular Localizable.strings and plural Localizable.stringsdict.
|
3
5
|
## Installation
|
4
6
|
`$ sudo gem install rescodegen`
|
5
7
|
|
6
8
|
## Usage
|
7
9
|
### Generate Code
|
8
|
-
`$ rescodegen -
|
10
|
+
`$ rescodegen -i Localizable.strings`
|
9
11
|
### Options
|
10
12
|
|
11
|
-
|Option|Value|Description |
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
|Option|Value|Required|Default|Description |
|
14
|
+
|---|---|---|---|---|
|
15
|
+
|`-i`|relative/path/to/Localizable.strings|✔️||The input file(s). Must be `.strings` or `.stringsdict` format. You may specify more than 1 file.|
|
16
|
+
|`-l`|swift or objc|❌|`swift`|The language of the generated code.|
|
17
|
+
|`-o`|relative/path/to/output/directory|❌|`.`|Where to save generated files.|
|
18
|
+
|`-p`|e.g. SH|❌||An optional prefix to apply to Objective-C types.|
|
16
19
|
## Example
|
17
20
|
### Localizable.strings
|
18
21
|
|
19
22
|
```
|
20
|
-
|
21
|
-
|
23
|
+
...
|
24
|
+
/* Error message to display when uploading an image fails. */
|
25
|
+
"Uploader.ErrorAlert.Message" = "The upload failed.";
|
26
|
+
...
|
27
|
+
```
|
28
|
+
### Localizable.stringsdict
|
22
29
|
|
23
|
-
|
24
|
-
|
30
|
+
```
|
31
|
+
...
|
32
|
+
<key>Uploader.ProgressLabel.Text</key>
|
33
|
+
<dict>
|
34
|
+
<key>NSStringLocalizedFormatKey</key>
|
35
|
+
<string>Uploading %#@images@.</string>
|
36
|
+
<key>images</key>
|
37
|
+
<dict>
|
38
|
+
<key>NSStringFormatSpecTypeKey</key>
|
39
|
+
<string>NSStringPluralRuleType</string>
|
40
|
+
<key>NSStringFormatValueTypeKey</key>
|
41
|
+
<string>d</string>
|
42
|
+
<key>one</key>
|
43
|
+
<string>one image</string>
|
44
|
+
<key>other</key>
|
45
|
+
<string>%d images</string>
|
46
|
+
</dict>
|
47
|
+
</dict>
|
48
|
+
...
|
25
49
|
```
|
26
50
|
### Generate Code
|
27
51
|
|
28
52
|
```
|
29
|
-
$ rescodegen -
|
30
|
-
$ rescodegen -
|
53
|
+
$ rescodegen -i Localizable.strings -i Localizable.stringsdict
|
54
|
+
$ rescodegen -i Localizable.strings -i Localizable.stringsdict -l objc
|
31
55
|
```
|
32
56
|
### Xcode
|
33
57
|
Drag the generated files into Xcode and add them to your target.
|
34
58
|
### Swift
|
35
|
-
Access
|
36
|
-
`Strings.Singular.
|
59
|
+
Access localized singular strings:
|
60
|
+
`Strings.Singular.uploader_errorAlert_message.localizedString` => "The upload failed."
|
61
|
+
Access localized plural strings:
|
62
|
+
`Strings.Plural.uploader_progressLabel_text.localizedString(1)` => "Uploading one image."
|
37
63
|
### Objective-C
|
38
|
-
Access
|
39
|
-
`LocalizedSingularString(
|
64
|
+
Access localized singular strings:
|
65
|
+
`LocalizedSingularString(SingularString_uploader_errorAlert_message)` => "The upload failed."
|
66
|
+
Access localized plural strings:
|
67
|
+
`LocalizedPluralString(PluralString_uploader_progressLabel_text, 2)` => "Uploading 2 images."
|
68
|
+
## Encoding
|
69
|
+
rescodegen currently only supports UTF-8 encoding.
|
data/Rakefile
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
3
|
|
4
|
-
|
4
|
+
task :test => [:unit, :acceptance] do
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
Rake::TestTask.new(:unit) do |t|
|
5
9
|
t.libs << "test"
|
6
10
|
t.libs << "lib"
|
7
11
|
t.test_files = FileList['test/**/*_tests.rb']
|
8
12
|
end
|
9
13
|
|
14
|
+
desc "Runs acceptance tests."
|
15
|
+
task :acceptance do
|
16
|
+
exec "rspec spec"
|
17
|
+
end
|
18
|
+
|
10
19
|
task :default => :test
|
data/bin/rescodegen
CHANGED
@@ -11,10 +11,13 @@ require 'optparse'
|
|
11
11
|
require 'rescodegen/code_generator/swift_strings_generator'
|
12
12
|
require 'rescodegen/code_generator/objc_header_strings_generator'
|
13
13
|
require 'rescodegen/code_generator/objc_main_strings_generator'
|
14
|
-
require 'rescodegen/key_generator/
|
14
|
+
require 'rescodegen/key_generator/key_generator'
|
15
|
+
require 'rescodegen/key_generator/code_safe_key_generator'
|
15
16
|
require 'rescodegen/code_formatter/code_formatter'
|
17
|
+
require 'rescodegen/key_reader/strings_key_reader'
|
18
|
+
require 'rescodegen/key_reader/stringsdict_key_reader'
|
16
19
|
|
17
|
-
options = { output: ".", language: "swift", prefix: "" }
|
20
|
+
options = { output: ".", language: "swift", prefix: "", input: [] }
|
18
21
|
|
19
22
|
parser = OptionParser.new do |opts|
|
20
23
|
opts.banner = "Usage: rescodegen [options] input_file"
|
@@ -29,27 +32,58 @@ parser = OptionParser.new do |opts|
|
|
29
32
|
opts.on("-p", "--prefix=PREFIX", "Optional prefix for Objective-C types.") do |p|
|
30
33
|
options[:prefix] = p
|
31
34
|
end
|
35
|
+
opts.on("-i", "--input=file1,file2", Array, "Accepts .strings or .stringsdict files.") do |i|
|
36
|
+
options[:input] += i
|
37
|
+
end
|
32
38
|
end
|
33
39
|
parser.parse!
|
34
40
|
|
35
41
|
abort "Invalid -l argument. Expects swift or objc." if !options[:language].match("swift|objc")
|
36
|
-
|
37
|
-
abort "Missing input_file.\n\n#{parser.help}" if input_file.nil?
|
42
|
+
abort "Missing -i argument. Must have at least 1 input file." if options[:input].size == 0
|
38
43
|
output_file = options[:output] + "/" + options[:prefix] + "Strings"
|
39
44
|
|
40
|
-
def generate_swift_file(
|
41
|
-
File.write(output_file + ".swift", Rescodegen::SwiftStringsGenerator.new.generate(
|
45
|
+
def generate_swift_file(singular_code_safe_keys, singular_keys, plural_code_safe_keys, plural_keys, output_file)
|
46
|
+
File.write(output_file + ".swift", Rescodegen::SwiftStringsGenerator.new.generate(singular_code_safe_keys, singular_keys, plural_code_safe_keys, plural_keys))
|
47
|
+
end
|
48
|
+
|
49
|
+
def generate_objc_files(singular_code_safe_keys, singular_keys, plural_code_safe_keys, plural_keys, output_file, prefix)
|
50
|
+
File.write(output_file + ".h", Rescodegen::ObjcHeaderStringsGenerator.new(prefix).generate(singular_code_safe_keys, singular_keys, plural_code_safe_keys, plural_keys))
|
51
|
+
File.write(output_file + ".m", Rescodegen::ObjcMainStringsGenerator.new(prefix).generate(singular_code_safe_keys, singular_keys, plural_code_safe_keys, plural_keys))
|
52
|
+
end
|
53
|
+
|
54
|
+
def abort_bad_input_file
|
55
|
+
abort "Only currenly supports .strings and .stringsdict files."
|
42
56
|
end
|
43
57
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
58
|
+
def generator_for_file(file, key_reader)
|
59
|
+
code_safe_key_generator = Rescodegen::CodeSafeKeyGenerator.new
|
60
|
+
generator = Rescodegen::KeyGenerator.new(key_reader, code_safe_key_generator, file)
|
47
61
|
end
|
48
62
|
|
49
|
-
|
50
|
-
|
51
|
-
|
63
|
+
abort_bad_input_file if options[:input].select { |file| file.end_with?(".strings") || file.end_with?(".stringsdict") }.empty?
|
64
|
+
|
65
|
+
singular_keys = []
|
66
|
+
singular_code_safe_keys = []
|
67
|
+
options[:input].select { |file| file.end_with?(".strings") }
|
68
|
+
.map { |file|
|
69
|
+
generator = generator_for_file(file, Rescodegen::StringsKeyReader.new)
|
70
|
+
singular_keys += generator.keys
|
71
|
+
singular_code_safe_keys += generator.code_safe_keys
|
72
|
+
}
|
73
|
+
|
74
|
+
plural_keys = []
|
75
|
+
plural_code_safe_keys = []
|
76
|
+
options[:input].select { |file| file.end_with?(".stringsdict") }
|
77
|
+
.map { |file|
|
78
|
+
generator = generator_for_file(file, Rescodegen::StringsdictKeyReader.new)
|
79
|
+
plural_keys += generator.keys
|
80
|
+
plural_code_safe_keys += generator.code_safe_keys
|
81
|
+
}
|
82
|
+
|
83
|
+
abort "The input file(s) did not contain any keys." if singular_keys.size == 0 && plural_keys.size == 0
|
84
|
+
|
52
85
|
formatter = Rescodegen::CodeFormatter.new
|
53
|
-
|
54
|
-
|
55
|
-
|
86
|
+
singular_code_safe_keys = singular_code_safe_keys.map { |k| formatter.format_string(k) }
|
87
|
+
plural_code_safe_keys = plural_code_safe_keys.map { |k| formatter.format_string(k) }
|
88
|
+
generate_swift_file(singular_code_safe_keys, singular_keys, plural_code_safe_keys, plural_keys, output_file) if options[:language] == "swift"
|
89
|
+
generate_objc_files(singular_code_safe_keys, singular_keys, plural_code_safe_keys, plural_keys, output_file, options[:prefix]) if options[:language] == "objc"
|
@@ -7,36 +7,49 @@ module Rescodegen
|
|
7
7
|
@prefix = prefix
|
8
8
|
end
|
9
9
|
|
10
|
-
def generate(
|
11
|
-
super(
|
12
|
-
enum_name = prefix "SingularString"
|
10
|
+
def generate(singular_keys, singular_values, plural_keys, plural_values)
|
11
|
+
super(singular_keys, singular_values, plural_keys, plural_values)
|
13
12
|
import_module("Foundation")
|
14
|
-
.
|
15
|
-
|
16
|
-
.
|
17
|
-
|
18
|
-
|
13
|
+
.singular_enum(singular_keys, singular_values)
|
14
|
+
.plural_enum(plural_keys, plural_values)
|
15
|
+
add_c_method("NSString*", prefix("LocalizedSingularString"), "#{singular_enum_name} singularString") if singular_keys.size != 0
|
16
|
+
add_c_method("NSString*", prefix("LocalizedPluralString"), "#{plural_enum_name} pluralString, ...") if plural_keys.size != 0
|
17
|
+
newline
|
19
18
|
@output
|
20
19
|
end
|
21
20
|
|
22
21
|
protected
|
23
22
|
|
23
|
+
def singular_enum(keys, values)
|
24
|
+
return self if keys.size == 0
|
25
|
+
newline
|
26
|
+
.start_enum(singular_enum_name, "NSInteger")
|
27
|
+
.add_cases(singular_enum_name, keys)
|
28
|
+
.finish_enum
|
29
|
+
end
|
30
|
+
|
31
|
+
def plural_enum(keys, values)
|
32
|
+
return self if keys.size == 0
|
33
|
+
newline
|
34
|
+
.start_enum(plural_enum_name, "NSInteger")
|
35
|
+
.add_cases(plural_enum_name, keys)
|
36
|
+
.finish_enum
|
37
|
+
end
|
38
|
+
|
24
39
|
def import_module(name)
|
25
40
|
@output += "@import #{name};"
|
26
|
-
newline
|
27
|
-
self
|
41
|
+
newline
|
28
42
|
end
|
29
43
|
|
30
44
|
def start_enum(name, type)
|
31
45
|
indent
|
32
46
|
@output += "typedef NS_ENUM(#{type}, #{name})"
|
33
47
|
open_brackets
|
34
|
-
self
|
35
48
|
end
|
36
49
|
|
37
|
-
def add_c_method(return_type, name,
|
50
|
+
def add_c_method(return_type, name, parameter_list)
|
38
51
|
newline
|
39
|
-
@output += "#{return_type} #{name}(#{
|
52
|
+
@output += "#{return_type} #{name}(#{parameter_list});"
|
40
53
|
self
|
41
54
|
end
|
42
55
|
|
@@ -54,7 +67,14 @@ module Rescodegen
|
|
54
67
|
indent
|
55
68
|
@output += "};"
|
56
69
|
newline
|
57
|
-
|
70
|
+
end
|
71
|
+
|
72
|
+
def singular_enum_name
|
73
|
+
prefix "SingularString"
|
74
|
+
end
|
75
|
+
|
76
|
+
def plural_enum_name
|
77
|
+
prefix "PluralString"
|
58
78
|
end
|
59
79
|
end
|
60
80
|
end
|
@@ -7,87 +7,115 @@ module Rescodegen
|
|
7
7
|
@prefix = prefix
|
8
8
|
end
|
9
9
|
|
10
|
-
def generate(
|
11
|
-
super(
|
12
|
-
enum_name = prefix "SingularString"
|
10
|
+
def generate(singular_keys, singular_values, plural_keys, plural_values)
|
11
|
+
super(singular_keys, singular_values, plural_keys, plural_values)
|
13
12
|
newline
|
14
13
|
.import_header(prefix("Strings.h"))
|
15
14
|
.newline
|
16
|
-
.
|
17
|
-
|
18
|
-
.add_cases(keys.map { |k| enum_name + "_" + k }, values)
|
19
|
-
.close_brackets
|
20
|
-
.close_brackets
|
21
|
-
.newline
|
15
|
+
.add_singular_methods(singular_keys, singular_values)
|
16
|
+
.add_plural_methods(plural_keys, plural_values)
|
22
17
|
@output
|
23
18
|
end
|
24
19
|
|
25
|
-
|
26
|
-
@output += "#import \"#{name}\""
|
27
|
-
self
|
28
|
-
end
|
20
|
+
protected
|
29
21
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
22
|
+
def add_singular_methods(keys, values)
|
23
|
+
return self if keys.size == 0
|
24
|
+
enum_name = prefix "SingularString"
|
25
|
+
start_c_method("NSString*", prefix("LocalizedSingularString"), "#{enum_name} singularString")
|
26
|
+
.start_switch("singularString")
|
27
|
+
.add_cases(keys.map { |k| enum_name + "_" + k }, values)
|
28
|
+
.close_brackets
|
29
|
+
.close_brackets
|
30
|
+
end
|
36
31
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
32
|
+
def add_plural_methods(keys, values)
|
33
|
+
return self if keys.size == 0
|
34
|
+
enum_name = prefix "PluralString"
|
35
|
+
start_c_method("NSString*", "NSStringFromPluralString", "#{enum_name} pluralString")
|
36
|
+
.start_switch("pluralString")
|
37
|
+
.add_cases(keys.map { |k| enum_name + "_" + k }, values)
|
38
|
+
.close_brackets
|
39
|
+
.close_brackets
|
40
|
+
.start_c_method("NSString*", prefix("LocalizedPluralString"), "#{enum_name} pluralString, ...")
|
41
|
+
.return_localized_plural_string
|
42
|
+
.close_brackets
|
43
|
+
end
|
44
|
+
|
45
|
+
def import_header(name)
|
46
|
+
@output += "#import \"#{name}\""
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_c_method(return_type, name, parameter_list)
|
51
|
+
newline
|
52
|
+
@output += "#{return_type} #{name}(#{parameter_list})"
|
53
|
+
open_brackets
|
54
|
+
end
|
55
|
+
|
56
|
+
def start_switch(value)
|
57
|
+
indent
|
58
|
+
@output += "switch (#{value})"
|
59
|
+
open_brackets
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_cases(keys, values)
|
63
|
+
i = 0
|
64
|
+
until i == keys.size
|
65
|
+
start_case(keys[i])
|
66
|
+
.return_value(localized_string(values[i]))
|
67
|
+
.finish_case
|
68
|
+
i += 1
|
69
|
+
end
|
70
|
+
add_default_case
|
71
|
+
end
|
43
72
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
start_case(keys[i])
|
48
|
-
.return_value(localized_string(values[i]))
|
73
|
+
def add_default_case
|
74
|
+
start_default_case
|
75
|
+
.return_value("@\"\"")
|
49
76
|
.finish_case
|
50
|
-
i += 1
|
51
77
|
end
|
52
|
-
add_default_case
|
53
|
-
self
|
54
|
-
end
|
55
78
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
79
|
+
def start_case(key)
|
80
|
+
indent
|
81
|
+
@output += "case #{key}:"
|
82
|
+
newline
|
83
|
+
increment_indent_level
|
84
|
+
end
|
61
85
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
86
|
+
def start_default_case
|
87
|
+
indent
|
88
|
+
@output += "default:"
|
89
|
+
newline
|
90
|
+
increment_indent_level
|
91
|
+
end
|
68
92
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
newline
|
73
|
-
increment_indent_level
|
74
|
-
self
|
75
|
-
end
|
93
|
+
def finish_case
|
94
|
+
decrement_indent_level
|
95
|
+
end
|
76
96
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
97
|
+
def return_value(value)
|
98
|
+
indent
|
99
|
+
@output += "return #{value};"
|
100
|
+
newline
|
101
|
+
end
|
81
102
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
newline
|
86
|
-
self
|
87
|
-
end
|
103
|
+
def localized_string(value)
|
104
|
+
return "NSLocalizedString(@\"#{value}\", @\"\")"
|
105
|
+
end
|
88
106
|
|
89
|
-
|
90
|
-
|
91
|
-
|
107
|
+
def return_localized_plural_string
|
108
|
+
add_line("va_list args")
|
109
|
+
.add_line("va_start(args, pluralString)")
|
110
|
+
.add_line("NSString *string = [[NSString alloc] initWithFormat:NSStringFromPluralString(pluralString) locale:[NSLocale currentLocale] arguments:args]")
|
111
|
+
.add_line("va_end(args)")
|
112
|
+
.add_line("return string")
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_line(line)
|
116
|
+
indent
|
117
|
+
@output += "#{line};"
|
118
|
+
newline
|
119
|
+
end
|
92
120
|
end
|
93
121
|
end
|
@@ -2,8 +2,9 @@
|
|
2
2
|
module Rescodegen
|
3
3
|
class StringsGenerator
|
4
4
|
|
5
|
-
def generate(
|
6
|
-
raise "Expects keys and values of equal sizes" if
|
5
|
+
def generate(singular_keys, singular_values, plural_keys, plural_values)
|
6
|
+
raise "Expects keys and values of equal sizes" if singular_keys.size != singular_values.size || plural_keys.size != plural_values.size
|
7
|
+
raise "Expects at least one key and one value" if singular_keys.size == 0 && plural_keys.size == 0
|
7
8
|
@output = ""
|
8
9
|
@tab_level = 0
|
9
10
|
end
|
@@ -23,7 +24,6 @@ module Rescodegen
|
|
23
24
|
@output += " {"
|
24
25
|
newline
|
25
26
|
increment_indent_level
|
26
|
-
self
|
27
27
|
end
|
28
28
|
|
29
29
|
def close_brackets
|
@@ -31,7 +31,6 @@ module Rescodegen
|
|
31
31
|
indent
|
32
32
|
@output += "}"
|
33
33
|
newline
|
34
|
-
self
|
35
34
|
end
|
36
35
|
|
37
36
|
def increment_indent_level
|
@@ -3,22 +3,40 @@ require_relative 'strings_generator'
|
|
3
3
|
module Rescodegen
|
4
4
|
class SwiftStringsGenerator < StringsGenerator
|
5
5
|
|
6
|
-
def generate(
|
7
|
-
super(
|
6
|
+
def generate(singular_keys, singular_values, plural_keys, plural_values)
|
7
|
+
super(singular_keys, singular_values, plural_keys, plural_values)
|
8
8
|
import_header("Foundation")
|
9
9
|
start_struct("Strings")
|
10
|
-
.
|
11
|
-
|
12
|
-
.start_computed_property("localizedString", "String")
|
13
|
-
.return_localized_string
|
14
|
-
.close_brackets
|
15
|
-
.close_brackets
|
10
|
+
.add_singular_enum(singular_keys, singular_values)
|
11
|
+
.add_plural_enum(plural_keys, plural_values)
|
16
12
|
.close_brackets
|
17
13
|
@output
|
18
14
|
end
|
19
15
|
|
20
16
|
protected
|
21
17
|
|
18
|
+
def add_singular_enum(keys, values)
|
19
|
+
return self if keys.size == 0
|
20
|
+
newline
|
21
|
+
.start_enum("Singular", "String")
|
22
|
+
.add_cases(keys, values)
|
23
|
+
.start_computed_property("localizedString", "String")
|
24
|
+
.return_localized_string
|
25
|
+
.close_brackets
|
26
|
+
.close_brackets
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_plural_enum(keys, values)
|
30
|
+
return self if keys.size == 0
|
31
|
+
newline
|
32
|
+
.start_enum("Plural", "String")
|
33
|
+
.add_cases(keys, values)
|
34
|
+
.start_function("localizedString", "args: CVarArgType...", "String")
|
35
|
+
.return_localized_plural_string
|
36
|
+
.close_brackets
|
37
|
+
close_brackets
|
38
|
+
end
|
39
|
+
|
22
40
|
def newline
|
23
41
|
@output += "\n"
|
24
42
|
self
|
@@ -26,22 +44,19 @@ module Rescodegen
|
|
26
44
|
|
27
45
|
def import_header(name)
|
28
46
|
@output += "import #{name}"
|
29
|
-
newline
|
30
|
-
self
|
47
|
+
newline
|
31
48
|
end
|
32
49
|
|
33
50
|
def start_struct(name)
|
51
|
+
newline
|
34
52
|
@output += "struct #{name}"
|
35
53
|
open_brackets
|
36
|
-
newline
|
37
|
-
self
|
38
54
|
end
|
39
55
|
|
40
56
|
def start_enum(name, type)
|
41
57
|
indent
|
42
58
|
@output += "enum #{name}: #{type}"
|
43
59
|
open_brackets
|
44
|
-
self
|
45
60
|
end
|
46
61
|
|
47
62
|
def add_cases(keys, values)
|
@@ -52,21 +67,35 @@ module Rescodegen
|
|
52
67
|
newline
|
53
68
|
end
|
54
69
|
newline
|
55
|
-
self
|
56
70
|
end
|
57
71
|
|
58
72
|
def start_computed_property(name, type)
|
59
73
|
indent
|
60
74
|
@output += "var #{name}: #{type}"
|
61
75
|
open_brackets
|
62
|
-
self
|
63
76
|
end
|
64
77
|
|
65
78
|
def return_localized_string
|
66
79
|
indent
|
67
80
|
@output += "return NSLocalizedString(rawValue, comment: \"\")"
|
68
81
|
newline
|
69
|
-
|
82
|
+
end
|
83
|
+
|
84
|
+
def start_function(name, parameter_list, return_type)
|
85
|
+
indent
|
86
|
+
@output += "func #{name}(#{parameter_list}) -> #{return_type}"
|
87
|
+
open_brackets
|
88
|
+
end
|
89
|
+
|
90
|
+
def return_localized_plural_string
|
91
|
+
add_line "let localized = NSLocalizedString(rawValue, comment: \"\")"
|
92
|
+
add_line "return String(format: localized, locale: NSLocale.currentLocale(), arguments: args)"
|
93
|
+
end
|
94
|
+
|
95
|
+
def add_line(line)
|
96
|
+
indent
|
97
|
+
@output += "#{line}"
|
98
|
+
newline
|
70
99
|
end
|
71
100
|
end
|
72
101
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
module Rescodegen
|
3
|
+
|
4
|
+
class CodeSafeKeyGenerator
|
5
|
+
|
6
|
+
def code_safe_keys_from_keys(keys)
|
7
|
+
keys.map { |key|
|
8
|
+
key.replace_string_format_specifiers
|
9
|
+
.replace_unsupported_characters
|
10
|
+
.replace_whitespace
|
11
|
+
.remove_duplicate_underscores
|
12
|
+
.trim_underscores
|
13
|
+
.protect_from_numbers
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
class String
|
21
|
+
def replace_string_format_specifiers
|
22
|
+
gsub(/%\.[0-9]f|%[a-zA-Z@]+/, "_")
|
23
|
+
end
|
24
|
+
|
25
|
+
def replace_unsupported_characters
|
26
|
+
gsub(/[^a-zA-Z0-9]/, "_")
|
27
|
+
end
|
28
|
+
|
29
|
+
def replace_whitespace
|
30
|
+
gsub(/\s+/, "_")
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_duplicate_underscores
|
34
|
+
gsub(/_+/, "_")
|
35
|
+
end
|
36
|
+
|
37
|
+
def trim_underscores
|
38
|
+
gsub(/^_|_$/, "")
|
39
|
+
end
|
40
|
+
|
41
|
+
def protect_from_numbers
|
42
|
+
sub(/(^[0-9])/, "_\\1")
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module Rescodegen
|
3
|
+
|
4
|
+
class KeyGenerator
|
5
|
+
|
6
|
+
attr_reader :key_reader
|
7
|
+
attr_reader :code_safe_key_generator
|
8
|
+
attr_reader :file_path
|
9
|
+
|
10
|
+
def initialize(key_reader, code_safe_key_generator, file_path)
|
11
|
+
@key_reader = key_reader
|
12
|
+
@code_safe_key_generator = code_safe_key_generator
|
13
|
+
@file_path = file_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def keys
|
17
|
+
key_reader.read_keys_from_lines File.open(file_path).readlines
|
18
|
+
end
|
19
|
+
|
20
|
+
def code_safe_keys
|
21
|
+
code_safe_key_generator.code_safe_keys_from_keys keys
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module Rescodegen
|
3
|
+
|
4
|
+
class StringsKeyReader
|
5
|
+
|
6
|
+
def read_keys_from_lines(lines)
|
7
|
+
lines.map(&method(:encode_line_with_utf8))
|
8
|
+
.select(&method(:line_contains_key))
|
9
|
+
.map(&method(:extract_key))
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def encode_line_with_utf8(line)
|
14
|
+
line.encode("UTF-8", :invalid=>:replace, :replace=>"?").encode('UTF-8')
|
15
|
+
end
|
16
|
+
|
17
|
+
def line_contains_key(line)
|
18
|
+
return false if line.size == 0
|
19
|
+
line[0] == "\""
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract_key(line)
|
23
|
+
line.sub(/\n$/, "")
|
24
|
+
.sub(/(")(.*)(" = ".*)/, "\\2")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/rescodegen/version.rb
CHANGED
data/rescodegen.gemspec
CHANGED
@@ -18,8 +18,12 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_runtime_dependency "plist", "= 3.2.0"
|
22
|
+
|
21
23
|
spec.add_development_dependency "bundler", "~> 1.11"
|
22
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
25
|
spec.add_development_dependency "minitest", "~> 5.0"
|
24
26
|
spec.add_development_dependency "simplecov", "~> 0.11"
|
27
|
+
spec.add_development_dependency "codeclimate-test-reporter", "~> 0.5"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.4"
|
25
29
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rescodegen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Henry
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: plist
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,34 @@ dependencies:
|
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0.11'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: codeclimate-test-reporter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.5'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.5'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.4'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.4'
|
69
111
|
description:
|
70
112
|
email:
|
71
113
|
- hello@seanhenry.codes
|
@@ -87,7 +129,10 @@ files:
|
|
87
129
|
- lib/rescodegen/code_generator/objc_main_strings_generator.rb
|
88
130
|
- lib/rescodegen/code_generator/strings_generator.rb
|
89
131
|
- lib/rescodegen/code_generator/swift_strings_generator.rb
|
90
|
-
- lib/rescodegen/key_generator/
|
132
|
+
- lib/rescodegen/key_generator/code_safe_key_generator.rb
|
133
|
+
- lib/rescodegen/key_generator/key_generator.rb
|
134
|
+
- lib/rescodegen/key_reader/strings_key_reader.rb
|
135
|
+
- lib/rescodegen/key_reader/stringsdict_key_reader.rb
|
91
136
|
- lib/rescodegen/version.rb
|
92
137
|
- rescodegen.gemspec
|
93
138
|
homepage: https://github.com/seanhenry/rescodegen
|
@@ -1,34 +0,0 @@
|
|
1
|
-
|
2
|
-
module Rescodegen
|
3
|
-
class StringsKeyGenerator
|
4
|
-
|
5
|
-
def self.create_from_file(input_file)
|
6
|
-
lines = File.open(input_file, "rb:UTF-16BE")
|
7
|
-
StringsKeyGenerator.new lines
|
8
|
-
end
|
9
|
-
|
10
|
-
def initialize(lines)
|
11
|
-
@keys = lines.map { |l| l.encode("UTF-8", :invalid=>:replace, :replace=>"?").encode('UTF-8') }
|
12
|
-
.reject { |l| l.strip == "" }
|
13
|
-
.select { |l| l[0] == "\"" }
|
14
|
-
.map do |line|
|
15
|
-
line.gsub(/\n$/, "")
|
16
|
-
.gsub(/(")(.*)(" = ".*)/, "\\2") # extracts key from "key" = "description"; format
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def keys
|
21
|
-
@keys
|
22
|
-
end
|
23
|
-
|
24
|
-
def code_safe_keys
|
25
|
-
@keys.map do |key|
|
26
|
-
key.gsub(/%\.[0-9]f|%[a-zA-Z@]+/, "_") # replace %d, %ld, %.2f etc
|
27
|
-
.gsub(/[^a-zA-Z0-9]/, "_") # replace unsupported characters
|
28
|
-
.gsub(/(\s|_)+/, "_") # replaces 1 or more occurance of whitespace and/or '_' with single '_'
|
29
|
-
.gsub(/^_|_$/, "") # remove _ from beginning and end
|
30
|
-
.gsub(/(^[0-9])/, "_\\1") # add underscore at beginning if starts with number
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|