1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-04-13 13:59:10 +08:00

feat(format.lua) add format.lua

This commit is contained in:
Eric Wong 2024-04-16 11:27:49 +08:00
parent ae6b976930
commit 1d8dbeb8bb
14 changed files with 267 additions and 68 deletions

View File

@ -1,7 +1,6 @@
# SpaceVim
[![twitter](https://img.spacevim.org/twitter.svg)](https://twitter.com/SpaceVim)
[![GPLv3 License](https://img.spacevim.org/license-GPLv3-blue.svg)](development/#证书)
SpaceVim is a modular configuration of Vim and Neovim.
It's inspired by spacemacs. It manages collections of plugins in layers,
@ -23,7 +22,4 @@ what packages to install.
- English: [https://spacevim.org/development/](https://spacevim.org/development/)
- Chinese: [https://spacevim.org/cn/development/](https://spacevim.org/cn/development/)
<!-- vim:set nowrap: -->

View File

@ -16,7 +16,7 @@
"
" 1. `format_on_save`: disabled by default.
" 2. `format_method`: set the format plugin, default plugin is `neoformat`.
" You can also use `vim-codefmt`.
" You can also use `vim-codefmt` or `format.nvim`
" 3. `silent_format`: Runs the formatter without any messages.
" 4. `format_notify_width`: set the neoformat notify window width.
" 5. `format_notify_timeout`: set the neoformat notify clear timeout. default
@ -57,6 +57,10 @@ function! SpaceVim#layers#format#plugins() abort
\ ['google/vim-glaive', {'merged' : 0, 'loadconf' : 1}],
\ ['google/vim-codefmt', {'merged' : 0}],
\ ]
elseif s:format_method ==# 'format.nvim'
return [
\ [g:_spacevim_root_dir . 'bundle/format.nvim', {'merged' : 0, 'loadconf' : 1, 'loadconf_before' : 1}],
\ ]
endif
endfunction
@ -66,6 +70,8 @@ function! SpaceVim#layers#format#config() abort
call SpaceVim#mapping#space#def('nnoremap', ['b', 'f'], 'Neoformat', 'format-code', 1)
elseif s:format_method ==# 'codefmt'
call SpaceVim#mapping#space#def('nnoremap', ['b', 'f'], 'FormatCode', 'format-code', 1)
elseif s:format_method ==# 'format.nvim'
call SpaceVim#mapping#space#def('nnoremap', ['b', 'f'], 'Format', 'format-code', 1)
endif
augroup spacevim_layer_format
autocmd!
@ -118,6 +124,8 @@ function! s:format() abort
undojoin | Neoformat
elseif s:format_method ==# 'codefmt'
undojoin | FormatCode
elseif s:format_method ==# 'format.nvim'
undojoin | Format
endif
endif
endfunction

View File

@ -0,0 +1,34 @@
local M = {}
local util = require('format.util')
local task = require('format.task')
function M.format(bang, user_input, start_line, end_line)
if not vim.o.modifiable then
return util.msg('buffer is not modifiable!')
end
local filetype = vim.o.filetype
if filetype == '' then
return util.msg('format: skip empty filetype')
end
local ok, default_formatter = pcall(require, 'format.ft.' .. filetype)
if not ok then
return util.msg('no formatter for ' .. filetype)
end
task.run({
bufnr = vim.fn.bufnr(),
stdin = vim.api.nvim_buf_get_lines(0, start_line - 1, end_line - 1, false),
start_line = start_line - 1,
end_line = end_line - 1,
formatter = default_formatter
})
end
function M.setup(opts) end
return M

View File

@ -0,0 +1,5 @@
local M = {}
M.custom_formatters = {}
return M

View File

@ -0,0 +1,5 @@
return {
exe = 'stylua',
args = {'-'},
stdin = true
}

View File

@ -0,0 +1,8 @@
if vim.fn.executable('prettier') == 1 then
return {
exe = vim.fn.exepath('prettier'),
name = 'prettier',
args = {'--stdin-filepath', 't.md'},
stdin = true
}
end

View File

@ -0,0 +1,93 @@
local M = {}
local jobid = -1
local job = require('spacevim.api.job')
local util = require('format.util')
local stdout = {}
local stderr = {}
local current_task
local function on_stdout(id, data)
for _, v in ipairs(data) do
table.insert(stdout, v)
end
end
local function on_stderr(id, data)
for _, v in ipairs(data) do
table.insert(stderr, v)
end
end
local function on_exit(id, code, single)
util.info(
'formatter: '
.. (current_task.formatter.name or current_task.formatter.exe)
.. ' exit code:'
.. code
.. ' single:'
.. single
)
if code == 0 and single == 0 then
if current_task.formatter.use_stderr then
vim.api.nvim_buf_set_lines(
current_task.bufnr,
current_task.start_line,
current_task.end_line,
false,
stderr
)
else
if table.concat(stdout, '\n') == table.concat(current_task.stdin, '\n') then
util.msg('no necessary changes')
else
util.msg((current_task.formatter.name or current_task.formatter.exe) .. ' formatted buffer')
vim.api.nvim_buf_set_lines(
current_task.bufnr,
current_task.start_line,
current_task.end_line,
false,
stdout
)
end
end
else
util.msg('formatter ' .. current_task.formatter.exe .. ' failed to run')
end
jobid = -1
end
function M.run(task)
if jobid > 0 then
util.msg('previous formatting command has not ended')
return
end
util.info('running formatter: ' .. task.formatter.exe)
local cmd = { task.formatter.exe }
for _, v in ipairs(task.formatter.args) do
table.insert(cmd, v)
end
stdout = {}
stderr = {}
current_task = task
jobid = job.start(cmd, {
on_stdout = on_stdout,
on_stderr = on_stderr,
on_exit = on_exit,
})
if jobid == -1 then
return util.msg('formatter is not executable: ' .. task.formatter.exe)
end
if task.formatter.stdin then
job.send(jobid, task.stdin)
job.send(jobid, nil)
end
end
return M

View File

@ -0,0 +1,14 @@
local M = {}
local nt = require('spacevim.api.notify')
local log = require('spacevim.logger').derive('format')
function M.msg(msg)
nt.notify(msg)
end
function M.info(msg)
log.info(msg)
end
return M

View File

@ -0,0 +1,8 @@
vim.api.nvim_create_user_command('Format', function(opts)
require('format').format(opts.bang, opts.args, opts.line1, opts.line2)
end, {
nargs = '*',
range = '%',
bang = true,
bar = true
})

View File

@ -2243,7 +2243,7 @@ LAYER OPTIONS
1. `format_on_save`: disabled by default.
2. `format_method`: set the format plugin, default plugin is `neoformat`.
You can also use `vim-codefmt`.
You can also use `vim-codefmt` or `format.nvim`
3. `silent_format`: Runs the formatter without any messages.
4. `format_notify_width`: set the neoformat notify window width.
5. `format_notify_timeout`: set the neoformat notify clear timeout. default

View File

@ -2627,5 +2627,4 @@ export PATH=$PATH:$HOME/.SpaceVim/bin
```
Use `svc` to open a file in the existing Vim server, or use `nsvc` to open a file in the existing Neovim server.
![server-and-client](https://img.spacevim.org/32554968-7164fe9c-c4d6-11e7-95f7-f6a6ea75e05b.gif)

View File

@ -23,7 +23,6 @@ The `format` layer provides code formatting for SpaceVim, with support for
[`codefmt`](https://github.com/google/vim-codefmt) underlying code
formatting plugins.
## Install
This layer is enabled by default. If you want to disable it, add the following to your configuration file:
@ -71,7 +70,7 @@ This layer is enabled by default. If you want to disable it, add the following t
```
- **`silent_format`**: Setting this to true will run the formatter silently without any messages. Default is
disabled.
disabled.
```toml
[[layers]]
@ -84,10 +83,8 @@ disabled.
neoformat is a formatting framework, all of it's options can be used in bootstrap function. You can read
`:help neoformat` for more info.
Here is an example for add formatter for java file, and it has been included into `lang#java` layer:
```viml
let g:neoformat_enabled_java = ['googlefmt']
let g:neoformat_java_googlefmt = {
@ -99,6 +96,6 @@ let g:neoformat_java_googlefmt = {
## Key bindings
| Key binding | Description |
| ----------- | ------------------------------------- |
| Key binding | Description |
| ----------- | ----------- |
| `SPC b f` | format whole buffer or selected lines |

View File

@ -46,28 +46,28 @@ local function new_job_obj(id, handle, opt, state)
end
local function default_dev() -- {{{
local env = vim.fn.environ()
env['NVIM'] = vim.v.servername
env['NVIM_LISTEN_ADDRESS'] = nil
env['NVIM_LOG_FILE'] = nil
env['VIMRUNTIME'] = nil
return env
local env = vim.fn.environ()
env['NVIM'] = vim.v.servername
env['NVIM_LISTEN_ADDRESS'] = nil
env['NVIM_LOG_FILE'] = nil
env['VIMRUNTIME'] = nil
return env
end
-- }}}
local function setup_env(env, clear_env) -- {{{
if clear_env then
return env
end
--- @type table<string,string|number>
env = vim.tbl_extend('force', default_dev(), env or {})
if clear_env then
return env
end
--- @type table<string,string|number>
env = vim.tbl_extend('force', default_dev(), env or {})
local renv = {} --- @type string[]
for k, v in pairs(env) do
renv[#renv + 1] = string.format('%s=%s', k, tostring(v))
end
local renv = {} --- @type string[]
for k, v in pairs(env) do
renv[#renv + 1] = string.format('%s=%s', k, tostring(v))
end
return renv
return renv
end
-- }}}
@ -157,7 +157,7 @@ function M.start(cmd, opts)
if data then
local stdout_data
_jobs['jobid_' .. current_id].state.stdout_eof, stdout_data =
buffered_data(_jobs['jobid_' .. current_id].state.stdout_eof, data)
buffered_data(_jobs['jobid_' .. current_id].state.stdout_eof, data)
vim.schedule(function()
opts.on_stdout(current_id, stdout_data)
end)
@ -168,7 +168,7 @@ function M.start(cmd, opts)
if data then
local stdout_data
_jobs['jobid_' .. current_id].state.stdout_eof, stdout_data =
buffered_data(_jobs['jobid_' .. current_id].state.stdout_eof, data)
buffered_data(_jobs['jobid_' .. current_id].state.stdout_eof, data)
vim.schedule(function()
opts.on_stdout(current_id, stdout_data, 'stdout')
end)
@ -184,7 +184,7 @@ function M.start(cmd, opts)
if data then
local stderr_data
_jobs['jobid_' .. current_id].state.stderr_eof, stderr_data =
buffered_data(_jobs['jobid_' .. current_id].state.stderr_eof, data)
buffered_data(_jobs['jobid_' .. current_id].state.stderr_eof, data)
vim.schedule(function()
opts.on_stderr(current_id, stderr_data)
end)
@ -195,7 +195,7 @@ function M.start(cmd, opts)
if data then
local stderr_data
_jobs['jobid_' .. current_id].state.stderr_eof, stderr_data =
buffered_data(_jobs['jobid_' .. current_id].state.stderr_eof, data)
buffered_data(_jobs['jobid_' .. current_id].state.stderr_eof, data)
vim.schedule(function()
opts.on_stderr(current_id, stderr_data, 'stderr')
end)
@ -207,35 +207,35 @@ function M.start(cmd, opts)
end
function M.send(id, data) -- {{{
local jobobj = _jobs['jobid_' .. id]
local jobobj = _jobs['jobid_' .. id]
if not jobobj then
error('can not find job:' .. id)
end
if not jobobj then
error('can not find job:' .. id)
end
local stdin = jobobj.state.stdin
local stdin = jobobj.state.stdin
if not stdin then
error('no stdin stream for jobid:' .. id)
end
if not stdin then
error('no stdin stream for jobid:' .. id)
end
if type(data) == 'table' then
for _, v in ipairs(data) do
stdin:write(v)
stdin:write('\n')
end
elseif type(data) == 'string' then
stdin:write(data)
if type(data) == 'table' then
for _, v in ipairs(data) do
stdin:write(v)
stdin:write('\n')
elseif data == nil then
stdin:write('', function()
stdin:shutdown(function()
if stdin then
stdin:close()
end
end)
end)
end
elseif type(data) == 'string' then
stdin:write(data)
stdin:write('\n')
elseif data == nil then
stdin:write('', function()
stdin:shutdown(function()
if stdin then
stdin:close()
end
end)
end)
end
end
function M.chanclose(id, t)
@ -245,14 +245,12 @@ function M.chanclose(id, t)
error('can not find job:' .. id)
end
if t == 'stdin' then
-- close stdio
local stdin = jobobj.state.stdin
if not stdin then
stdin:shutdown(function()
if stdin then
stdin:close()
end
end)
if stdin and stdin:is_active() then
stdin:close()
end
elseif t == 'stdout' then
elseif t == 'stderr' then
else
@ -267,12 +265,6 @@ function M.stop(id)
return
end
-- close stdio
local stdin = jobobj.state.stdin
if stdin and stdin:is_active() then
stdin:close()
end
local handle = jobobj.handle
handle:kill(6)
end

View File

@ -0,0 +1,40 @@
local job = require('spacevim.api.job')
local nt = require('spacevim.api.notify')
local text = {}
local function on_stdout(id, data)
nt.notify('stdout:' .. #data)
for _, v in ipairs(data) do
table.insert(text, v)
end
end
local function on_stderr(id, data)
nt.notify('stdout')
end
local function on_exit(id, code, single)
nt.notify('done')
-- vim.api.nvim_buf_set_lines(0, 0, -1, false, text)
end
-- local id = job.start({ vim.fn.exepath('prettier'), '--stdin-filepath', 't.md' }, {
local id = job.start({ 'cat' }, {
on_stdout = on_stdout,
on_stderr = on_stderr,
on_exit = on_exit,
})
job.send(id, vim.api.nvim_buf_get_lines(0, 0, -1, false))
job.send(id, nil)
-- job.chanclose(id, 'stdin')
-- job.stop(id)
-- local id2 = vim.fn.jobstart('cat', {
-- on_stdout = on_stdout,
-- on_stderr = on_stderr,
-- on_exit = on_exit,
-- })
--
-- vim.fn.chansend(id2, vim.api.nvim_buf_get_lines(0, 0, -1, false))
-- vim.fn.jobstop(id2)