editorconfig 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7e98dc00d0f7381091b9a6e113edd9daeb81c17a
4
+ data.tar.gz: e3e6ce431efd27f8923ac24b62db91b8cf308cd5
5
+ SHA512:
6
+ metadata.gz: eb431952375d5514474e35274db0e3ef24050774c7052a2c677ce1e5a8aef1010c91c90f67de603f9dc2e8fdd9be294ff5951da2e85ef4b3d42377466ea19813
7
+ data.tar.gz: 5fd815440431dac67177cf84443e78362cf5581d58663b9ebbb80575243f15dab116b6fd24c1cfb5126409286baf34c3296be35b1600c65a76a4e703f51746e1
@@ -0,0 +1,197 @@
1
+ require "editor_config/version"
2
+
3
+ module EditorConfig
4
+ CONFIG_FILENAME = ".editorconfig".freeze
5
+
6
+ INDENT_STYLE = "indent_style".freeze
7
+ INDENT_SIZE = "indent_size".freeze
8
+ TAB_WIDTH = "tab_width".freeze
9
+ END_OF_LINE = "end_of_line".freeze
10
+ CHARSET = "charset".freeze
11
+ TRIM_TRAILING_WHITESPACE = "trim_trailing_whitespace".freeze
12
+ INSERT_FINAL_NEWLINE = "insert_final_newline".freeze
13
+ MAX_LINE_LENGTH = "max_line_length".freeze
14
+
15
+ TRUE = "true".freeze
16
+ FALSE = "false".freeze
17
+
18
+ SPACE = "space".freeze
19
+ TAB = "tab".freeze
20
+
21
+ CR = "cr".freeze
22
+ LF = "lf".freeze
23
+ CRLF = "crlf".freeze
24
+
25
+ LATIN1 = "latin1".freeze
26
+ UTF_8 = "utf-8".freeze
27
+ UTF_8_BOM = "utf-8-bom".freeze
28
+ UTF_16BE = "utf-16be".freeze
29
+ UTF_16LE = "utf-16le".freeze
30
+
31
+ # Internal: Maximum number of bytes to read per line. Lines over this limit
32
+ # will be truncated.
33
+ MAX_LINE = 200
34
+
35
+ # Internal: Maximum byte length of section name Strings. Names over this limit
36
+ # will be truncated.
37
+ MAX_SECTION_NAME = 500
38
+
39
+ # Internal: Maximum byte length of property name String. Names over this limit
40
+ # will be truncated.
41
+ MAX_PROPERTY_NAME = 500
42
+
43
+ # Public: Parse a `.editorconfig` from a string.
44
+ #
45
+ # io - a String containing the contents of a `.editorconfig` file.
46
+ #
47
+ # Returns a hash of sections from the config file. Each section will be a
48
+ # hash of key/value pairs for that section. The only top-level key that
49
+ # won't have a Hash value is "root" which if it exists will be set to
50
+ # `true`.
51
+ #
52
+ # Possible key/value pairs for sections are as follows:
53
+ # "indent_style" - :tab, :space or nil.
54
+ # "indent_size" - :tab, an integer between 1-64, or nil.
55
+ # "tab_width" - an integer between 1-64, or nil.
56
+ # "end_of_line" - :lf, :cr, :crlf or nil.
57
+ # "charset" - "latin1", "utf-8", "utf-8-bom", "utf-16be",
58
+ # "utf-16le" or nil.
59
+ # "trim_trailing_whitespace" - true, false or nil.
60
+ # "insert_final_newline" - true, false or nil.
61
+ #
62
+ # If either of these keys exist but the value is nil, the key existed in the
63
+ # editorconfig but it's value was invalid or not supported.
64
+ #
65
+ # An example hash would look like this:
66
+ # {
67
+ # "root" => true,
68
+ # "*.rb" => {
69
+ # "indent_style" => :space
70
+ # "indent_size" => 2,
71
+ # "charset" => "utf-8"
72
+ # }
73
+ # }
74
+ def self.parse(io, version: SPEC_VERSION)
75
+ # if !io.force_encoding("UTF-8").valid_encoding?
76
+ # raise ArgumentError, "editorconfig syntax must be valid UTF-8"
77
+ # end
78
+
79
+ root = false
80
+ out_hash = {}
81
+ last_section = nil
82
+
83
+ io.each_line do |line|
84
+ case line.chomp
85
+ when /\Aroot(\s+)?\=(\s+)?true\Z/
86
+ root = true
87
+ when /\A\[(?<name>.+)\]\Z/
88
+ # section marker
89
+ last_section = Regexp.last_match[:name][0, MAX_SECTION_NAME]
90
+ out_hash[last_section] = {}
91
+ when /\A(?<name>[[:word:]]+)(\s+)?\=(\s+)?(?<value>.+)\Z/
92
+ match = Regexp.last_match
93
+ name, value = match[:name][0, MAX_PROPERTY_NAME], match[:value]
94
+
95
+ if last_section
96
+ out_hash[last_section][name] = value
97
+ else
98
+ out_hash[name] = value
99
+ end
100
+ end
101
+ end
102
+
103
+ return out_hash, root
104
+ end
105
+
106
+ def self.preprocess(config, version: SPEC_VERSION)
107
+ config = config.reduce({}) { |h, (k, v)| h[k.downcase] = v; h }
108
+
109
+ [
110
+ INDENT_STYLE,
111
+ INDENT_SIZE,
112
+ TAB_WIDTH,
113
+ END_OF_LINE,
114
+ CHARSET,
115
+ TRIM_TRAILING_WHITESPACE,
116
+ INSERT_FINAL_NEWLINE,
117
+ MAX_LINE_LENGTH
118
+ ].each do |key|
119
+ if config.key?(key)
120
+ config[key] = config[key].downcase
121
+ end
122
+ end
123
+
124
+ if !config.key?(TAB_WIDTH) && config.key?(INDENT_SIZE) && config[INDENT_SIZE] != TAB
125
+ config[TAB_WIDTH] = config[INDENT_SIZE]
126
+ end
127
+
128
+ if version > "0.9"
129
+ if !config.key?(INDENT_SIZE) && config[INDENT_STYLE] == TAB
130
+ if config.key?(TAB_WIDTH)
131
+ config[INDENT_SIZE] = config[TAB_WIDTH]
132
+ else
133
+ config[INDENT_SIZE] = TAB
134
+ end
135
+ end
136
+ end
137
+
138
+ config
139
+ end
140
+
141
+ def self.fnmatch?(pattern, path)
142
+ flags = File::FNM_PATHNAME | File::FNM_EXTGLOB
143
+ File.fnmatch?(pattern, path, flags) ||
144
+ File.fnmatch?(pattern, File.basename(path), flags)
145
+ end
146
+
147
+ def self.load(path, config: CONFIG_FILENAME, version: SPEC_VERSION)
148
+ hash = {}
149
+
150
+ traverse(path).each do |subpath|
151
+ config_path = subpath == "" ? config : "#{subpath}/#{config}"
152
+ config_data = yield config_path
153
+ next unless config_data
154
+
155
+ ini, root = parse(config_data, version: version)
156
+
157
+ ini.each do |pattern, properties|
158
+ matcher = subpath == "" ? pattern : "#{subpath}/#{pattern}"
159
+ if fnmatch?(matcher, path)
160
+ hash = properties.merge(hash)
161
+ end
162
+ end
163
+
164
+ if root
165
+ break
166
+ end
167
+ end
168
+
169
+ hash
170
+ end
171
+
172
+ def self.traverse(path)
173
+ paths = []
174
+ parts = path.split("/", -1)
175
+
176
+ idx = parts.length - 1
177
+
178
+ while idx > 0
179
+ paths << parts[0, idx].join("/")
180
+ idx -= 1
181
+ end
182
+
183
+ if path.start_with?("/")
184
+ paths[-1] = "/"
185
+ else
186
+ paths << ""
187
+ end
188
+
189
+ paths
190
+ end
191
+
192
+ def self.load_file(*args)
193
+ EditorConfig.load(*args) do |path|
194
+ File.read(path) if File.exist?(path)
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,4 @@
1
+ module EditorConfig
2
+ VERSION = "0.1.1"
3
+ SPEC_VERSION = "0.9.1"
4
+ end
@@ -0,0 +1 @@
1
+ require "editor_config"
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: editorconfig
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - GitHub
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/editor_config.rb
20
+ - lib/editor_config/version.rb
21
+ - lib/editorconfig.rb
22
+ homepage:
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 2.4.5
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: EditorConfig core library written in Ruby
46
+ test_files: []