Module: EditorConfig
- Defined in:
- lib/editor_config.rb,
lib/editor_config/version.rb
Constant Summary collapse
- CONFIG_FILENAME =
".editorconfig".freeze
- INDENT_STYLE =
"indent_style".freeze
- INDENT_SIZE =
"indent_size".freeze
- TAB_WIDTH =
"tab_width".freeze
- END_OF_LINE =
"end_of_line".freeze
- CHARSET =
"charset".freeze
- TRIM_TRAILING_WHITESPACE =
"trim_trailing_whitespace".freeze
- INSERT_FINAL_NEWLINE =
"insert_final_newline".freeze
- MAX_LINE_LENGTH =
"max_line_length".freeze
- TRUE =
"true".freeze
- FALSE =
"false".freeze
- SPACE =
"space".freeze
- TAB =
"tab".freeze
- CR =
"cr".freeze
- LF =
"lf".freeze
- CRLF =
"crlf".freeze
- LATIN1 =
"latin1".freeze
- UTF_8 =
"utf-8".freeze
- UTF_8_BOM =
"utf-8-bom".freeze
- UTF_16BE =
"utf-16be".freeze
- UTF_16LE =
"utf-16le".freeze
- MAX_LINE =
Internal: Maximum number of bytes to read per line. Lines over this limit will be truncated.
200
- MAX_SECTION_NAME =
Internal: Maximum byte length of section name Strings. Names over this limit will be truncated.
500
- MAX_PROPERTY_NAME =
Internal: Maximum byte length of property name String. Names over this limit will be truncated.
500
- VERSION =
"0.1.1"
- SPEC_VERSION =
"0.9.1"
Class Method Summary collapse
- .fnmatch?(pattern, path) ⇒ Boolean
- .load(path, config: CONFIG_FILENAME, version: SPEC_VERSION) ⇒ Object
- .load_file(*args) ⇒ Object
-
.parse(io, version: SPEC_VERSION) ⇒ Object
Public: Parse a ‘.editorconfig` from a string.
- .preprocess(config, version: SPEC_VERSION) ⇒ Object
- .traverse(path) ⇒ Object
Class Method Details
.fnmatch?(pattern, path) ⇒ Boolean
141 142 143 144 145 |
# File 'lib/editor_config.rb', line 141 def self.fnmatch?(pattern, path) flags = File::FNM_PATHNAME | File::FNM_EXTGLOB File.fnmatch?(pattern, path, flags) || File.fnmatch?(pattern, File.basename(path), flags) end |
.load(path, config: CONFIG_FILENAME, version: SPEC_VERSION) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/editor_config.rb', line 147 def self.load(path, config: CONFIG_FILENAME, version: SPEC_VERSION) hash = {} traverse(path).each do |subpath| config_path = subpath == "" ? config : "#{subpath}/#{config}" config_data = yield config_path next unless config_data ini, root = parse(config_data, version: version) ini.each do |pattern, properties| matcher = subpath == "" ? pattern : "#{subpath}/#{pattern}" if fnmatch?(matcher, path) hash = properties.merge(hash) end end if root break end end hash end |
.load_file(*args) ⇒ Object
192 193 194 195 196 |
# File 'lib/editor_config.rb', line 192 def self.load_file(*args) EditorConfig.load(*args) do |path| File.read(path) if File.exist?(path) end end |
.parse(io, version: SPEC_VERSION) ⇒ Object
Public: Parse a ‘.editorconfig` from a string.
io - a String containing the contents of a ‘.editorconfig` file.
Returns a hash of sections from the config file. Each section will be a hash of key/value pairs for that section. The only top-level key that won’t have a Hash value is “root” which if it exists will be set to ‘true`.
Possible key/value pairs for sections are as follows:
"indent_style" - :tab, :space or nil.
"indent_size" - :tab, an integer between 1-64, or nil.
"tab_width" - an integer between 1-64, or nil.
"end_of_line" - :lf, :cr, :crlf or nil.
"charset" - "latin1", "utf-8", "utf-8-bom", "utf-16be",
"utf-16le" or nil.
"trim_trailing_whitespace" - true, false or nil.
"insert_final_newline" - true, false or nil.
If either of these keys exist but the value is nil, the key existed in the editorconfig but it’s value was invalid or not supported.
An example hash would look like this: {
"root" => true,
"*.rb" => {
"indent_style" => :space
"indent_size" => 2,
"charset" => "utf-8"
}
}
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/editor_config.rb', line 74 def self.parse(io, version: SPEC_VERSION) # if !io.force_encoding("UTF-8").valid_encoding? # raise ArgumentError, "editorconfig syntax must be valid UTF-8" # end root = false out_hash = {} last_section = nil io.each_line do |line| case line.chomp when /\Aroot(\s+)?\=(\s+)?true\Z/ root = true when /\A\[(?<name>.+)\]\Z/ # section marker last_section = Regexp.last_match[:name][0, MAX_SECTION_NAME] out_hash[last_section] = {} when /\A(?<name>[[:word:]]+)(\s+)?\=(\s+)?(?<value>.+)\Z/ match = Regexp.last_match name, value = match[:name][0, MAX_PROPERTY_NAME], match[:value] if last_section out_hash[last_section][name] = value else out_hash[name] = value end end end return out_hash, root end |
.preprocess(config, version: SPEC_VERSION) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/editor_config.rb', line 106 def self.preprocess(config, version: SPEC_VERSION) config = config.reduce({}) { |h, (k, v)| h[k.downcase] = v; h } [ INDENT_STYLE, INDENT_SIZE, TAB_WIDTH, END_OF_LINE, CHARSET, TRIM_TRAILING_WHITESPACE, INSERT_FINAL_NEWLINE, MAX_LINE_LENGTH ].each do |key| if config.key?(key) config[key] = config[key].downcase end end if !config.key?(TAB_WIDTH) && config.key?(INDENT_SIZE) && config[INDENT_SIZE] != TAB config[TAB_WIDTH] = config[INDENT_SIZE] end if version > "0.9" if !config.key?(INDENT_SIZE) && config[INDENT_STYLE] == TAB if config.key?(TAB_WIDTH) config[INDENT_SIZE] = config[TAB_WIDTH] else config[INDENT_SIZE] = TAB end end end config end |
.traverse(path) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/editor_config.rb', line 172 def self.traverse(path) paths = [] parts = path.split("/", -1) idx = parts.length - 1 while idx > 0 paths << parts[0, idx].join("/") idx -= 1 end if path.start_with?("/") paths[-1] = "/" else paths << "" end paths end |