sbdchd / neoformat

:sparkles: A (Neo)vim plugin for formatting code.
BSD 2-Clause "Simplified" License
2k stars 189 forks source link

`g:neoformat_run_all_formatters = 1` can break multiple formatters #256

Open aetherknight opened 5 years ago

aetherknight commented 5 years ago

g:neoformat_run_all_formatters doesn't seem to properly pass the output from one formatter to the next -- it seems llike neoformat sometimes cuts off the last line if a previous formatter changed the number of lines in the output (when formatting the whole file).

My reproduction example below uses isort, yapf, and Python, but I suspect this issue affects more than just my situation.

Configuration

Vim version:

VIM - Vi IMproved 8.1 (2018 May 18, compiled Dec 28 2018 15:41:18)
macOS version
Included patches: 1-577
Compiled by MacPorts
Huge version without GUI.  Features included (+) or not (-):
+acl               +extra_search      +mouse_netterm     +tag_old_static
+arabic            +farsi             +mouse_sgr         -tag_any_white
+autocmd           +file_in_path      -mouse_sysmouse    -tcl
+autochdir         +find_in_path      +mouse_urxvt       +termguicolors
-autoservername    +float             +mouse_xterm       +terminal
-balloon_eval      +folding           +multi_byte        +terminfo
+balloon_eval_term -footer            +multi_lang        +termresponse
-browse            +fork()            -mzscheme          +textobjects
++builtin_terms    +gettext           +netbeans_intg     +timers
+byte_offset       -hangul_input      +num64             +title
+channel           +iconv             +packages          -toolbar
+cindent           +insert_expand     +path_extra        +user_commands
-clientserver      +job               -perl              +vartabs
+clipboard         +jumplist          +persistent_undo   +vertsplit
+cmdline_compl     +keymap            +postscript        +virtualedit
+cmdline_hist      +lambda            +printer           +visual
+cmdline_info      +langmap           +profile           +visualextra
+comments          +libcall           -python            +viminfo
+conceal           +linebreak         -python3           +vreplace
+cryptv            +lispindent        +quickfix          +wildignore
-cscope            +listcmds          +reltime           +wildmenu
+cursorbind        +localmap          +rightleft         +windows
+cursorshape       -lua               -ruby              +writebackup
+dialog_con        +menu              +scrollbind        -X11
+diff              +mksession         +signs             -xfontset
+digraphs          +modify_fname      +smartindent       -xim
-dnd               +mouse             +startuptime       -xpm
-ebcdic            -mouseshape        +statusline        -xsmp
+emacs_tags        +mouse_dec         -sun_workshop      -xterm_clipboard
+eval              -mouse_gpm         +syntax            -xterm_save
+ex_extra          -mouse_jsbterm     +tag_binary
   system vimrc file: "/opt/local/etc/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/opt/local/share/vim"
Compilation: /usr/bin/clang -c -I. -Iproto -DHAVE_CONFIG_H   -I/opt/local/include -isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -DMACOS_X -DMACOS_X_DARWIN  -pipe -Os -isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -arch x86_64 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: /usr/bin/clang   -L/opt/local/lib -Wl,-headerpad_max_install_names -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -arch x86_64 -o vim        -lm  -lncurses -liconv -lintl -framework AppKit

neoformat version: the tip of HEAD as of a few minutes ago: 6b66c20fadd489460422104a62279a0cd8b35eda

Relevant .vimrc configuration:

let g:neoformat_enabled_python = ['isort', 'yapf']
let g:neoformat_verbose = 1

Relevant isort configuration (eg, in setup.cfg):

[isort]
force_single_line=True  # will cause the first line of the sample below to become 2 lines

(yapf config doesn't matter for this example)

Input file (Python)

from __future__ import absolute_import, print_function

def hello():
    print(
        "hello"
    )

Expected output file

from __future__ import absolute_import
from __future__ import print_function

def hello():
    print("hello")

First run output

I run: :Neoformat

However, after the first run, the output file is (yapf failed to run):

from __future__ import absolute_import
from __future__ import print_function

def hello():
    print(
        "hello"
    )

The verbose output for this run is:

Neoformat: ['from __future__ import absolute_import, print_function', '', 'def hello():', '    print(', '        "hello"', '    )']
Neoformat: isort - --quiet 2> /var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: using stdin
Neoformat: ['from __future__ import absolute_import', 'from __future__ import print_function', '', '', 'def hello():', '    print(', '        "hello"', '    )']
Neoformat: [0]
Neoformat: 0
Neoformat: stderr output redirected to file/var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: []
Neoformat: running next formatter
Neoformat: ['from __future__ import absolute_import', 'from __future__ import print_function', '', '', 'def hello():', '    print(']
Neoformat: yapf 2> /var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: using stdin
Neoformat: []
Neoformat: [0]
Neoformat: 1
Neoformat: stderr output redirected to file/var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: ['yapf: 7:EOF in multi-line statement']
Neoformat: 1
Neoformat: trying next formatter
Neoformat: formatters yapf failed to run
Neoformat: isort formatted buffer

If you look at the list of lines being formatted (as an array of strings), the last entry disappears between the output from isort and the input to yapf.

Running neoformat a second time

If I run :Neoformat a second time, it successfully runs yapf, and provides me with my expected output.

(see above for expected file output)

The verbose neoformat output for the second run:

Neoformat: ['from __future__ import absolute_import', 'from __future__ import print_function', '', '', 'def hello():', '    print(', '        "hello"', '    )']
Neoformat: isort - --quiet 2> /var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: using stdin
Neoformat: ['from __future__ import absolute_import', 'from __future__ import print_function', '', '', 'def hello():', '    print(', '        "hello"', '    )']
Neoformat: [0]
Neoformat: 0
Neoformat: stderr output redirected to file/var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: []
Neoformat: running next formatter
Neoformat: ['from __future__ import absolute_import', 'from __future__ import print_function', '', '', 'def hello():', '    print(', '        "hello"', '    )']
Neoformat: yapf 2> /var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: using stdin
Neoformat: ['from __future__ import absolute_import', 'from __future__ import print_function', '', '', 'def hello():', '    print("hello")']
Neoformat: [0]
Neoformat: 0
Neoformat: stderr output redirected to file/var/folders/ky/z9bzxr3j0cx1s4_946qpk5fr0000gn/T/neoformat/stderr.log
Neoformat: []
Neoformat: running next formatter
Neoformat: yapf formatted buffer
samtay commented 4 years ago

Ah! I couldn't figure out what was going wrong, but this is what's biting me as well. I'll go ahead and use your fork until this gets merged :)