mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #21633 from gpanders/editorconfig
Builtin EditorConfig support
This commit is contained in:
commit
d56c603caf
89
runtime/doc/editorconfig.txt
Normal file
89
runtime/doc/editorconfig.txt
Normal file
@ -0,0 +1,89 @@
|
||||
*editorconfig.txt* Nvim
|
||||
|
||||
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
|
||||
EditorConfig integration *editorconfig*
|
||||
|
||||
Nvim natively supports EditorConfig. When a file is opened, Nvim searches
|
||||
upward through all of the parent directories of that file looking for
|
||||
".editorconfig" files. Each of these is parsed and any properties that match
|
||||
the opened file are applied.
|
||||
|
||||
For more information on EditorConfig, see https://editorconfig.org/.
|
||||
|
||||
*g:editorconfig_enable*
|
||||
EditorConfig integration can be disabled by adding >lua
|
||||
|
||||
vim.g.editorconfig_enable = false
|
||||
<
|
||||
to the user's |init.lua| file (or the Vimscript equivalent to |init.vim|).
|
||||
|
||||
*b:editorconfig*
|
||||
When Nvim finds a valid .editorconfig file it will store the applied
|
||||
properties in the buffer variable |b:editorconfig|.
|
||||
|
||||
*editorconfig-properties*
|
||||
The following properties are supported by default:
|
||||
|
||||
*editorconfig_root*
|
||||
root If "true", then stop searching for .editorconfig files
|
||||
in parent directories. This property must be at the
|
||||
top-level of the .editorconfig file (i.e. it must not
|
||||
be within a glob section).
|
||||
|
||||
*editorconfig_charset*
|
||||
charset One of "utf-8", "utf-8-bom", "latin1", "utf-16be", or
|
||||
"utf-16le". Sets the 'fileencoding' and 'bomb'
|
||||
options.
|
||||
|
||||
*editorconfig_end_of_line*
|
||||
end_of_line One of "lf", "crlf", or "cr". These correspond to
|
||||
setting 'fileformat' to "unix", "dos", or "mac",
|
||||
respectively.
|
||||
|
||||
*editorconfig_indent_style*
|
||||
indent_style One of "tab" or "space". Sets the 'expandtab' option.
|
||||
|
||||
*editorconfig_indent_size*
|
||||
indent_size A number indicating the size of a single indent.
|
||||
Alternatively, use the value "tab" to use the value of
|
||||
the tab_width property. Sets the 'shiftwidth' and
|
||||
'softtabstop'.
|
||||
|
||||
*editorconfig_insert_final_newline*
|
||||
insert_final_newline "true" or "false" to ensure the file always has a
|
||||
trailing newline as its last byte. Sets the
|
||||
'fixendofline' and 'endofline' options.
|
||||
|
||||
*editorconfig_max_line_length*
|
||||
max_line_length A number indicating the maximum length of a single
|
||||
line. Sets the 'textwidth' option.
|
||||
|
||||
*editorconfig_tab_width*
|
||||
tab_width The display size of a single tab character. Sets the
|
||||
'tabstop' option.
|
||||
|
||||
*editorconfig_trim_trailing_whitespace*
|
||||
trim_trailing_whitespace
|
||||
When "true", trailing whitespace is automatically
|
||||
removed when the buffer is written.
|
||||
|
||||
*editorconfig-custom-properties*
|
||||
New properties can be added by adding a new entry to the "properties" table.
|
||||
The table key is a property name and the value is a callback function which
|
||||
accepts the number of the buffer to be modified, the value of the property
|
||||
in the .editorconfig file, and (optionally) a table containing all of the
|
||||
other properties and their values (useful for properties which depend on other
|
||||
properties). The value is always a string and must be coerced if necessary.
|
||||
Example: >lua
|
||||
|
||||
require('editorconfig').properties.foo = function(bufnr, val, opts)
|
||||
if opts.charset and opts.charset ~= "utf-8" then
|
||||
error("foo can only be set when charset is utf-8", 0)
|
||||
end
|
||||
vim.b[bufnr].foo = val
|
||||
end
|
||||
<
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
@ -50,6 +50,13 @@ NEW FEATURES *news-features*
|
||||
|
||||
The following new APIs or features were added.
|
||||
|
||||
• EditorConfig support is now builtin. This is enabled by default and happens
|
||||
automatically. To disable it, users should add >lua
|
||||
|
||||
vim.g.editorconfig_enable = false
|
||||
<
|
||||
(or the Vimscript equivalent) to their |config| file.
|
||||
|
||||
• Added a |vim.lsp.codelens.clear()| function to clear codelenses.
|
||||
|
||||
• |vim.inspect_pos()|, |vim.show_pos()| and |:Inspect| allow a user to get or show items
|
||||
|
246
runtime/lua/editorconfig.lua
Normal file
246
runtime/lua/editorconfig.lua
Normal file
@ -0,0 +1,246 @@
|
||||
local M = {}
|
||||
|
||||
M.properties = {}
|
||||
|
||||
--- Modified version of the builtin assert that does not include error position information
|
||||
---
|
||||
---@param v any Condition
|
||||
---@param message string Error message to display if condition is false or nil
|
||||
---@return any v if not false or nil, otherwise an error is displayed
|
||||
---
|
||||
---@private
|
||||
local function assert(v, message)
|
||||
return v or error(message, 0)
|
||||
end
|
||||
|
||||
--- Show a warning message
|
||||
---
|
||||
---@param msg string Message to show
|
||||
---
|
||||
---@private
|
||||
local function warn(msg, ...)
|
||||
vim.notify(string.format(msg, ...), vim.log.levels.WARN, {
|
||||
title = 'editorconfig',
|
||||
})
|
||||
end
|
||||
|
||||
function M.properties.charset(bufnr, val)
|
||||
assert(
|
||||
vim.tbl_contains({ 'utf-8', 'utf-8-bom', 'latin1', 'utf-16be', 'utf-16le' }, val),
|
||||
'charset must be one of "utf-8", "utf-8-bom", "latin1", "utf-16be", or "utf-16le"'
|
||||
)
|
||||
if val == 'utf-8' or val == 'utf-8-bom' then
|
||||
vim.bo[bufnr].fileencoding = 'utf-8'
|
||||
vim.bo[bufnr].bomb = val == 'utf-8-bom'
|
||||
elseif val == 'utf-16be' then
|
||||
vim.bo[bufnr].fileencoding = 'utf-16'
|
||||
else
|
||||
vim.bo[bufnr].fileencoding = val
|
||||
end
|
||||
end
|
||||
|
||||
function M.properties.end_of_line(bufnr, val)
|
||||
vim.bo[bufnr].fileformat = assert(
|
||||
({ lf = 'unix', crlf = 'dos', cr = 'mac' })[val],
|
||||
'end_of_line must be one of "lf", "crlf", or "cr"'
|
||||
)
|
||||
end
|
||||
|
||||
function M.properties.indent_style(bufnr, val, opts)
|
||||
assert(val == 'tab' or val == 'space', 'indent_style must be either "tab" or "space"')
|
||||
vim.bo[bufnr].expandtab = val == 'space'
|
||||
if val == 'tab' and not opts.indent_size then
|
||||
vim.bo[bufnr].shiftwidth = 0
|
||||
vim.bo[bufnr].softtabstop = 0
|
||||
end
|
||||
end
|
||||
|
||||
function M.properties.indent_size(bufnr, val, opts)
|
||||
if val == 'tab' then
|
||||
vim.bo[bufnr].shiftwidth = 0
|
||||
vim.bo[bufnr].softtabstop = 0
|
||||
else
|
||||
local n = assert(tonumber(val), 'indent_size must be a number')
|
||||
vim.bo[bufnr].shiftwidth = n
|
||||
vim.bo[bufnr].softtabstop = -1
|
||||
if not opts.tab_width then
|
||||
vim.bo[bufnr].tabstop = n
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.properties.tab_width(bufnr, val)
|
||||
vim.bo[bufnr].tabstop = assert(tonumber(val), 'tab_width must be a number')
|
||||
end
|
||||
|
||||
function M.properties.max_line_length(bufnr, val)
|
||||
local n = tonumber(val)
|
||||
if n then
|
||||
vim.bo[bufnr].textwidth = n
|
||||
else
|
||||
assert(val == 'off', 'max_line_length must be a number or "off"')
|
||||
vim.bo[bufnr].textwidth = 0
|
||||
end
|
||||
end
|
||||
|
||||
function M.properties.trim_trailing_whitespace(bufnr, val)
|
||||
assert(
|
||||
val == 'true' or val == 'false',
|
||||
'trim_trailing_whitespace must be either "true" or "false"'
|
||||
)
|
||||
if val == 'true' then
|
||||
vim.api.nvim_create_autocmd('BufWritePre', {
|
||||
group = 'editorconfig',
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
local view = vim.fn.winsaveview()
|
||||
vim.api.nvim_command('silent! undojoin')
|
||||
vim.api.nvim_command('silent keepjumps keeppatterns %s/\\s\\+$//e')
|
||||
vim.fn.winrestview(view)
|
||||
end,
|
||||
})
|
||||
else
|
||||
vim.api.nvim_clear_autocmds({
|
||||
event = 'BufWritePre',
|
||||
group = 'editorconfig',
|
||||
buffer = bufnr,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function M.properties.insert_final_newline(bufnr, val)
|
||||
assert(val == 'true' or val == 'false', 'insert_final_newline must be either "true" or "false"')
|
||||
vim.bo[bufnr].fixendofline = val == 'true'
|
||||
vim.bo[bufnr].endofline = val == 'true'
|
||||
end
|
||||
|
||||
--- Modified version of |glob2regpat()| that does not match path separators on *.
|
||||
---
|
||||
--- This function replaces single instances of * with the regex pattern [^/]*. However, the star in
|
||||
--- the replacement pattern also gets interpreted by glob2regpat, so we insert a placeholder, pass
|
||||
--- it through glob2regpat, then replace the placeholder with the actual regex pattern.
|
||||
---
|
||||
---@param glob string Glob to convert into a regular expression
|
||||
---@return string Regular expression
|
||||
---
|
||||
---@private
|
||||
local function glob2regpat(glob)
|
||||
local placeholder = '@@PLACEHOLDER@@'
|
||||
return (
|
||||
string.gsub(
|
||||
vim.fn.glob2regpat(
|
||||
vim.fn.substitute(
|
||||
string.gsub(glob, '{(%d+)%.%.(%d+)}', '[%1-%2]'),
|
||||
'\\*\\@<!\\*\\*\\@!',
|
||||
placeholder,
|
||||
'g'
|
||||
)
|
||||
),
|
||||
placeholder,
|
||||
'[^/]*'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
--- Parse a single line in an EditorConfig file
|
||||
---
|
||||
---@param line string Line
|
||||
---@return string|nil If the line contains a pattern, the glob pattern
|
||||
---@return string|nil If the line contains a key-value pair, the key
|
||||
---@return string|nil If the line contains a key-value pair, the value
|
||||
---
|
||||
---@private
|
||||
local function parse_line(line)
|
||||
if line:find('^%s*[^ #;]') then
|
||||
local glob = (line:match('%b[]') or ''):match('^%s*%[(.*)%]%s*$')
|
||||
if glob then
|
||||
return glob, nil, nil
|
||||
end
|
||||
|
||||
local key, val = line:match('^%s*([^:= ][^:=]-)%s*[:=]%s*(.-)%s*$')
|
||||
if key ~= nil and val ~= nil then
|
||||
return nil, key:lower(), val:lower()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Parse options from an .editorconfig file
|
||||
---
|
||||
---@param filepath string File path of the file to apply EditorConfig settings to
|
||||
---@param dir string Current directory
|
||||
---@return table Table of options to apply to the given file
|
||||
---
|
||||
---@private
|
||||
local function parse(filepath, dir)
|
||||
local pat = nil
|
||||
local opts = {}
|
||||
local f = io.open(dir .. '/.editorconfig')
|
||||
if f then
|
||||
for line in f:lines() do
|
||||
local glob, key, val = parse_line(line)
|
||||
if glob then
|
||||
glob = glob:find('/') and (dir .. '/' .. glob:gsub('^/', '')) or ('**/' .. glob)
|
||||
local ok, regpat = pcall(glob2regpat, glob)
|
||||
if ok then
|
||||
pat = vim.regex(regpat)
|
||||
else
|
||||
pat = nil
|
||||
warn('editorconfig: Error occurred while parsing glob pattern "%s": %s', glob, regpat)
|
||||
end
|
||||
elseif key ~= nil and val ~= nil then
|
||||
if key == 'root' then
|
||||
opts.root = val == 'true'
|
||||
elseif pat and pat:match_str(filepath) then
|
||||
opts[key] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
return opts
|
||||
end
|
||||
|
||||
--- Configure the given buffer with options from an .editorconfig file
|
||||
---
|
||||
---@param bufnr number Buffer number to configure
|
||||
---
|
||||
---@private
|
||||
function M.config(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
local path = vim.fs.normalize(vim.api.nvim_buf_get_name(bufnr))
|
||||
if vim.bo[bufnr].buftype ~= '' or not vim.bo[bufnr].modifiable or path == '' then
|
||||
return
|
||||
end
|
||||
|
||||
local opts = {}
|
||||
for parent in vim.fs.parents(path) do
|
||||
for k, v in pairs(parse(path, parent)) do
|
||||
if opts[k] == nil then
|
||||
opts[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
if opts.root then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local applied = {}
|
||||
for opt, val in pairs(opts) do
|
||||
if val ~= 'unset' then
|
||||
local func = M.properties[opt]
|
||||
if func then
|
||||
local ok, err = pcall(func, bufnr, val, opts)
|
||||
if ok then
|
||||
applied[opt] = val
|
||||
else
|
||||
warn('editorconfig: invalid value for option %s: %s. %s', opt, val, err)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vim.b[bufnr].editorconfig = applied
|
||||
end
|
||||
|
||||
return M
|
@ -1378,13 +1378,13 @@ local filename = {
|
||||
npmrc = 'dosini',
|
||||
['/etc/yum.conf'] = 'dosini',
|
||||
['.npmrc'] = 'dosini',
|
||||
['.editorconfig'] = 'dosini',
|
||||
['/etc/pacman.conf'] = 'confini',
|
||||
['mpv.conf'] = 'confini',
|
||||
dune = 'dune',
|
||||
jbuild = 'dune',
|
||||
['dune-workspace'] = 'dune',
|
||||
['dune-project'] = 'dune',
|
||||
['.editorconfig'] = 'editorconfig',
|
||||
['elinks.conf'] = 'elinks',
|
||||
['mix.lock'] = 'elixir',
|
||||
['filter-rules'] = 'elmfilt',
|
||||
|
11
runtime/plugin/editorconfig.lua
Normal file
11
runtime/plugin/editorconfig.lua
Normal file
@ -0,0 +1,11 @@
|
||||
if vim.g.editorconfig_enable == false or vim.g.editorconfig_enable == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local group = vim.api.nvim_create_augroup('editorconfig', {})
|
||||
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufRead', 'BufFilePost' }, {
|
||||
group = group,
|
||||
callback = function(args)
|
||||
require('editorconfig').config(args.buf)
|
||||
end,
|
||||
})
|
18
runtime/syntax/editorconfig.vim
Normal file
18
runtime/syntax/editorconfig.vim
Normal file
@ -0,0 +1,18 @@
|
||||
runtime! syntax/dosini.vim
|
||||
unlet! b:current_syntax
|
||||
|
||||
syntax match editorconfigInvalidProperty "^\s*\zs\w\+\ze\s*="
|
||||
syntax keyword editorconfigProperty root
|
||||
|
||||
lua<<
|
||||
local props = {}
|
||||
for k in pairs(require('editorconfig').properties) do
|
||||
props[#props + 1] = k
|
||||
end
|
||||
vim.cmd(string.format('syntax keyword editorconfigProperty %s', table.concat(props, ' ')))
|
||||
.
|
||||
|
||||
hi def link editorconfigInvalidProperty Error
|
||||
hi def link editorconfigProperty dosiniLabel
|
||||
|
||||
let b:current_syntax = 'editorconfig'
|
@ -162,7 +162,7 @@ let s:filename_checks = {
|
||||
\ 'dnsmasq': ['/etc/dnsmasq.conf', '/etc/dnsmasq.d/file', 'any/etc/dnsmasq.conf', 'any/etc/dnsmasq.d/file'],
|
||||
\ 'dockerfile': ['Containerfile', 'Dockerfile', 'dockerfile', 'file.Dockerfile', 'file.dockerfile', 'Dockerfile.debian', 'Containerfile.something'],
|
||||
\ 'dosbatch': ['file.bat'],
|
||||
\ 'dosini': ['.editorconfig', '/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap'],
|
||||
\ 'dosini': ['/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap'],
|
||||
\ 'dot': ['file.dot', 'file.gv'],
|
||||
\ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'],
|
||||
\ 'dtd': ['file.dtd'],
|
||||
@ -174,6 +174,7 @@ let s:filename_checks = {
|
||||
\ 'dylanlid': ['file.lid'],
|
||||
\ 'ecd': ['file.ecd'],
|
||||
\ 'edif': ['file.edf', 'file.edif', 'file.edo'],
|
||||
\ 'editorconfig': ['.editorconfig'],
|
||||
\ 'eelixir': ['file.eex', 'file.leex'],
|
||||
\ 'elinks': ['elinks.conf'],
|
||||
\ 'elixir': ['file.ex', 'file.exs', 'mix.lock'],
|
||||
|
194
test/functional/plugin/editorconfig_spec.lua
Normal file
194
test/functional/plugin/editorconfig_spec.lua
Normal file
@ -0,0 +1,194 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local clear = helpers.clear
|
||||
local command = helpers.command
|
||||
local eq = helpers.eq
|
||||
local pathsep = helpers.get_pathsep()
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
|
||||
local testdir = 'Xtest-editorconfig'
|
||||
|
||||
local function test_case(name, expected)
|
||||
local filename = testdir .. pathsep .. name
|
||||
command('edit ' .. filename)
|
||||
for opt, val in pairs(expected) do
|
||||
eq(val, curbufmeths.get_option(opt), name)
|
||||
end
|
||||
end
|
||||
|
||||
setup(function()
|
||||
helpers.mkdir_p(testdir)
|
||||
helpers.write_file(
|
||||
testdir .. pathsep .. '.editorconfig',
|
||||
[[
|
||||
root = true
|
||||
|
||||
[3_space.txt]
|
||||
indent_style = space
|
||||
indent_size = 3
|
||||
tab_width = 3
|
||||
|
||||
[4_space.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
tab_width = 8
|
||||
|
||||
[space.txt]
|
||||
indent_style = space
|
||||
indent_size = tab
|
||||
|
||||
[tab.txt]
|
||||
indent_style = tab
|
||||
|
||||
[4_tab.txt]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
|
||||
[4_tab_width_of_8.txt]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 8
|
||||
|
||||
[lf.txt]
|
||||
end_of_line = lf
|
||||
|
||||
[crlf.txt]
|
||||
end_of_line = crlf
|
||||
|
||||
[cr.txt]
|
||||
end_of_line = cr
|
||||
|
||||
[utf-8.txt]
|
||||
charset = utf-8
|
||||
|
||||
[utf-8-bom.txt]
|
||||
charset = utf-8-bom
|
||||
|
||||
[utf-16be.txt]
|
||||
charset = utf-16be
|
||||
|
||||
[utf-16le.txt]
|
||||
charset = utf-16le
|
||||
|
||||
[latin1.txt]
|
||||
charset = latin1
|
||||
|
||||
[with_newline.txt]
|
||||
insert_final_newline = true
|
||||
|
||||
[without_newline.txt]
|
||||
insert_final_newline = false
|
||||
|
||||
[trim.txt]
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[no_trim.txt]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[max_line_length.txt]
|
||||
max_line_length = 42
|
||||
]]
|
||||
)
|
||||
end)
|
||||
|
||||
teardown(function()
|
||||
helpers.rmdir(testdir)
|
||||
end)
|
||||
|
||||
describe('editorconfig', function()
|
||||
before_each(function()
|
||||
-- Remove -u NONE so that plugins (i.e. editorconfig.lua) are loaded
|
||||
clear({ args_rm = { '-u' } })
|
||||
end)
|
||||
|
||||
it('sets indent options', function()
|
||||
test_case('3_space.txt', {
|
||||
expandtab = true,
|
||||
shiftwidth = 3,
|
||||
softtabstop = -1,
|
||||
tabstop = 3,
|
||||
})
|
||||
|
||||
test_case('4_space.py', {
|
||||
expandtab = true,
|
||||
shiftwidth = 4,
|
||||
softtabstop = -1,
|
||||
tabstop = 8,
|
||||
})
|
||||
|
||||
test_case('space.txt', {
|
||||
expandtab = true,
|
||||
shiftwidth = 0,
|
||||
softtabstop = 0,
|
||||
})
|
||||
|
||||
test_case('tab.txt', {
|
||||
expandtab = false,
|
||||
shiftwidth = 0,
|
||||
softtabstop = 0,
|
||||
})
|
||||
|
||||
test_case('4_tab.txt', {
|
||||
expandtab = false,
|
||||
shiftwidth = 4,
|
||||
softtabstop = -1,
|
||||
tabstop = 4,
|
||||
})
|
||||
|
||||
test_case('4_tab_width_of_8.txt', {
|
||||
expandtab = false,
|
||||
shiftwidth = 4,
|
||||
softtabstop = -1,
|
||||
tabstop = 8,
|
||||
})
|
||||
end)
|
||||
|
||||
it('sets end-of-line options', function()
|
||||
test_case('lf.txt', { fileformat = 'unix' })
|
||||
test_case('crlf.txt', { fileformat = 'dos' })
|
||||
test_case('cr.txt', { fileformat = 'mac' })
|
||||
end)
|
||||
|
||||
it('sets encoding options', function()
|
||||
test_case('utf-8.txt', { fileencoding = 'utf-8', bomb = false })
|
||||
test_case('utf-8-bom.txt', { fileencoding = 'utf-8', bomb = true })
|
||||
test_case('utf-16be.txt', { fileencoding = 'utf-16', bomb = false })
|
||||
test_case('utf-16le.txt', { fileencoding = 'utf-16le', bomb = false })
|
||||
test_case('latin1.txt', { fileencoding = 'latin1', bomb = false })
|
||||
end)
|
||||
|
||||
it('sets newline options', function()
|
||||
test_case('with_newline.txt', { fixendofline = true, endofline = true })
|
||||
test_case('without_newline.txt', { fixendofline = false, endofline = false })
|
||||
end)
|
||||
|
||||
it('respects trim_trailing_whitespace', function()
|
||||
local filename = testdir .. pathsep .. 'trim.txt'
|
||||
-- luacheck: push ignore 613
|
||||
local untrimmed = [[
|
||||
This line ends in whitespace
|
||||
So does this one
|
||||
And this one
|
||||
But not this one
|
||||
]]
|
||||
-- luacheck: pop
|
||||
local trimmed = untrimmed:gsub('%s+\n', '\n')
|
||||
|
||||
helpers.write_file(filename, untrimmed)
|
||||
command('edit ' .. filename)
|
||||
command('write')
|
||||
command('bdelete')
|
||||
eq(trimmed, helpers.read_file(filename))
|
||||
|
||||
filename = testdir .. pathsep .. 'no_trim.txt'
|
||||
helpers.write_file(filename, untrimmed)
|
||||
command('edit ' .. filename)
|
||||
command('write')
|
||||
command('bdelete')
|
||||
eq(untrimmed, helpers.read_file(filename))
|
||||
end)
|
||||
|
||||
it('sets textwidth', function()
|
||||
test_case('max_line_length.txt', { textwidth = 42 })
|
||||
end)
|
||||
end)
|
Loading…
Reference in New Issue
Block a user