Skip to content

Commit

Permalink
Allowing passing of ranges directly to formatting tools
Browse files Browse the repository at this point in the history
Neoformat supports formatting only part of a file, but it just passes
that chunk to formatting tools. A lot of tools need the context of the
surrounding lines, but support passing the requested range as an
argument.

This commit adds support for ranges by allowing certain variables to be
substituted in the arguments. In that case the 'range' option should be
set to '1' to indicate that the tool itself will handle the range.
  • Loading branch information
bzvl committed Sep 5, 2018
1 parent c8bc4ec commit ba1be90
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 9 deletions.
43 changes: 35 additions & 8 deletions autoload/neoformat.vim
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,42 @@ function! s:neoformat(bang, user_input, start_line, end_line) abort
continue
endif

let stdin = getbufline(bufnr('%'), a:start_line, a:end_line)
if cmd.range
" Pass the entire buffer, the formatter itself takes a range.
let stdin = getbufline(bufnr('%'), 1, '$')
else
let lines_after = getbufline(bufnr('%'), a:end_line + 1, '$')
let lines_before = getbufline(bufnr('%'), 1, a:start_line - 1)
let stdin = getbufline(bufnr('%'), a:start_line, a:end_line)
end

let original_buffer = getbufline(bufnr('%'), 1, '$')

let exe = cmd.exe
let replacements = {
\ 'start_byte': line2byte(a:start_line),
\ 'end_byte': line2byte(a:end_line),
\ 'bytes': line2byte(a:end_line) - line2byte(a:start_line),
\ 'start_line': a:start_line,
\ 'end_line': a:end_line,
\ 'lines': a:end_line - a:start_line,
\ }

for [key, value] in items(replacements)
let exe = substitute(exe, '<'.key.'>', value, 'g')
endfor

call neoformat#utils#log(stdin)

call neoformat#utils#log(cmd.exe)
call neoformat#utils#log(exe)
if cmd.stdin
call neoformat#utils#log('using stdin')
let stdin_str = join(stdin, "\n")
let stdout = split(system(cmd.exe, stdin_str), '\n')
let stdout = split(system(exe, stdin_str), '\n')
else
call neoformat#utils#log('using tmp file')
call writefile(stdin, cmd.tmp_file_path)
let stdout = split(system(cmd.exe), '\n')
let stdout = split(system(exe), '\n')
endif

" read from /tmp file if formatter replaces file on format
Expand All @@ -108,11 +130,15 @@ function! s:neoformat(bang, user_input, start_line, end_line) abort
call neoformat#utils#log_file_content(cmd.stderr_log)
endif
if process_ran_succesfully
" 1. append the lines that are before and after the formatterd content
let lines_after = getbufline(bufnr('%'), a:end_line + 1, '$')
let lines_before = getbufline(bufnr('%'), 1, a:start_line - 1)
if cmd.range
let new_buffer = stdout
else
" 1. append the lines that are before and after the formatterd content
let lines_after = getbufline(bufnr('%'), a:end_line + 1, '$')
let lines_before = getbufline(bufnr('%'), 1, a:start_line - 1)
let new_buffer = lines_before + stdout + lines_after
endif

let new_buffer = lines_before + stdout + lines_after
if new_buffer !=# original_buffer

call s:deletelines(len(new_buffer), line('$'))
Expand Down Expand Up @@ -274,6 +300,7 @@ function! s:generate_cmd(definition, filetype) abort
\ 'name': a:definition.exe,
\ 'replace': get(a:definition, 'replace', 0),
\ 'tmp_file_path': path,
\ 'range': get(a:definition, 'range', 0),
\ 'valid_exit_codes': get(a:definition, 'valid_exit_codes', [0]),
\ }
endfunction
Expand Down
9 changes: 8 additions & 1 deletion autoload/neoformat/formatters/javascript.vim
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,15 @@ endfunction
function! neoformat#formatters#javascript#prettier() abort
return {
\ 'exe': 'prettier',
\ 'args': ['--stdin', '--stdin-filepath', '%:p'],
\ 'args': ['--stdin',
\ '--stdin-filepath',
\ '%:p',
\ '--range-start',
\ '<start_byte>',
\ '--range-end',
\ '<end_byte>'],
\ 'stdin': 1,
\ 'range': 1,
\ }
endfunction

Expand Down
2 changes: 2 additions & 0 deletions autoload/neoformat/formatters/python.vim
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ endfunction
function! neoformat#formatters#python#yapf() abort
return {
\ 'exe': 'yapf',
\ 'args': ['--lines', '<start_line>-<end_line>'],
\ 'stdin': 1,
\ 'range': 1,
\ }
endfunction

Expand Down
33 changes: 33 additions & 0 deletions doc/neoformat.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Introduction |neoformat-introduction|
Install |neoformat-install|
Usage |neoformat-usage|
Managing Undo History |neoformat-managing-undo-history|
Argument Templates neoformat-argument-templates
Supported Filetypes |neoformat-supported-filetypes|

==============================================================================
Expand Down Expand Up @@ -92,6 +93,9 @@ Options:
| `stderr` | used to specify whether stderr output should be read along with
the stdin, otherwise redirects stderr to `stderr.log` file in neoformat's
temporary directory | default 0 | optional
| `range` | formatter takes range as argument when using visual formatting. when set to 1, the entire buffer
will be passed in, the range shoudl be passed as an argument to the formatter |
default: 0 | optional
| `no_append` | do not append the `path` of the file to the formatter command,
used when the `path` is in the middle of a command | default: 0 |
optional
Expand Down Expand Up @@ -202,6 +206,35 @@ When |undojoin| is used this way pressing |u| will "skip over" the Neoformat
changes - it will revert both the changes made by Neoformat and the change
that caused Neoformat to be invoked.

==============================================================================
ARGUMENT TEMPLATES *neoformat-argument-templates*

The following strings will be expanded in the 'args' field:

- <start_line> - starting line of range
- <end_line> - ending line of range
- <lines> - number of lines in range
- <start_byte> - starting byte of range (from line2byte)
- <end_byte> - ending byte of range (from line2byte)
- <bytes> - number of bytes in range
- any expressions supported by |expand()|

Example:

let g:neoformat_cpp_clangformat = {
\ 'exe': 'clang-format',
\ 'args': ['-lines=<start_line>:<end_line>'],
\ 'range': 1,
\ 'stdin', 1,
\ }

let g:neoformat_cpp_clangformat = {
\ 'exe': 'clang-format',
\ 'args': ['-offset=<start_byte>', '-length=<bytes>'],
\ 'range': 1,
\ 'stdin', 1,
\ }

==============================================================================
SUPPORTED FILETYPES *neoformat-supported-filetypes*

Expand Down

0 comments on commit ba1be90

Please sign in to comment.