1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
105
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
|
local global_options = { check_same = true }
local function stdio_formatter(cmd, options)
local function apply(win, range, pos)
local size = win.file.size
local all = { start = 0, finish = size }
if range == nil then
range = all
end
local command = type(cmd) == "function" and cmd(win, range, pos) or cmd
local check_same = (options and options.check_same ~= nil) and options.check_same or global_options.check_same
local check = check_same == true or (type(check_same) == "number" and check_same >= size)
local status, out, err = vis:pipe(win.file, all, command)
if status ~= 0 then
vis:message(err)
elseif out == nil or out == "" then
vis:info("No output from formatter")
elseif not check or win.file:content(all) ~= out then
local start, finish = range.start, range.finish
win.file:delete(range)
win.file:insert(start, out:sub(start + 1, finish + (out:len() - size)))
end
return pos
end
return {
apply = apply,
options = options or { ranged = type(cmd) == "function" },
}
end
local function with_filename(win, option)
if win.file.path then
return option .. "'" .. win.file.path:gsub("'", "\\'") .. "'"
else
return ""
end
end
local formatters = {}
formatters = {
bash = stdio_formatter(function(win)
return "shfmt " .. with_filename(win, "--filename ") .. " -"
end),
csharp = stdio_formatter("dotnet csharpier"),
go = stdio_formatter("gofmt"),
lua = {
pick = function(win)
local _, out = vis:pipe(
win.file,
{ start = 0, finish = win.file.size },
"test -e .lua-format && echo luaformatter || echo stylua"
)
return formatters[out:gsub("\n$", "")]
end,
},
luaformatter = stdio_formatter("lua-format"),
markdown = stdio_formatter(function(win)
if win.options and win.options.colorcolumn ~= 0 then
return "prettier --parser markdown --prose-wrap always "
.. ("--print-width " .. (win.options.colorcolumn - 1) .. " ")
.. with_filename(win, "--stdin-filepath ")
else
return "prettier --parser markdown " .. with_filename(win, "--stdin-filepath ")
end
end, { ranged = false }),
powershell = stdio_formatter([[
"$( (command -v powershell.exe || command -v pwsh) 2>/dev/null )" -c '
Invoke-Formatter -ScriptDefinition `
([IO.StreamReader]::new([Console]::OpenStandardInput()).ReadToEnd())
' | sed -e :a -e '/^[\r\n]*$/{$d;N;};/\n$/ba'
]]),
rust = stdio_formatter("rustfmt"),
stylua = stdio_formatter(function(win, range)
if range and (range.start ~= 0 or range.finish ~= win.file.size) then
return "stylua -s --range-start "
.. range.start
.. " --range-end "
.. range.finish
.. with_filename(win, " --stdin-filepath ")
.. " -"
else
return "stylua -s " .. with_filename(win, "--stdin-filepath ") .. " -"
end
end),
text = stdio_formatter(function(win)
if win.options and win.options.colorcolumn ~= 0 then
return "fmt -w " .. (win.options.colorcolumn - 1)
else
return "fmt"
end
end, { ranged = false }),
}
local function getwinforfile(file)
for win in vis:windows() do
if win and win.file and win.file.path == file.path then
return win
end
end
end
local function apply(file_or_keys, range, pos)
local win = type(file_or_keys) ~= "string" and getwinforfile(file_or_keys) or vis.win
local ret = type(file_or_keys) ~= "string" and function()
return pos
end or function()
return 0
end
pos = pos or win.selection.pos
local formatter = formatters[win.syntax]
if formatter and formatter.pick then
formatter = formatter.pick(win)
end
if formatter == nil then
vis:info("No formatter for " .. win.syntax)
return ret()
end
if range ~= nil and not formatter.options.ranged and range.start ~= 0 and range.finish ~= win.file.size then
vis:info("Formatter for " .. win.syntax .. " does not support ranges")
return ret()
end
pos = formatter.apply(win, range, pos) or pos
vis:redraw()
win.selection.pos = pos
return ret()
end
return {
formatters = formatters,
options = global_options,
apply = apply,
stdio_formatter = stdio_formatter,
with_filename = with_filename,
}
|