diff --git a/autoload/sj/sh.vim b/autoload/sj/sh.vim index 9256cf63..72d9e752 100644 --- a/autoload/sj/sh.vim +++ b/autoload/sj/sh.vim @@ -12,6 +12,15 @@ function! sj#sh#SplitBySemicolon() return 1 endfunction +function! sj#sh#SplitWithBackslash() + if !search('\S', 'Wc', line('.')) + return 0 + endif + + exe "normal! i\\\" + return 1 +endfunction + function! sj#sh#JoinWithSemicolon() if !nextnonblank(line('.') + 1) return 0 @@ -20,3 +29,12 @@ function! sj#sh#JoinWithSemicolon() call sj#Keeppatterns('s/;\=\s*\n\_s*/; /e') return 1 endfunction + +function! sj#sh#JoinBackslashedLine() + if getline('.') !~ '\\\s*$' + return 0 + endif + + call sj#Keeppatterns('s/\\\=\s*\n\_s*//e') + return 1 +endfunction diff --git a/doc/splitjoin.txt b/doc/splitjoin.txt index b55c4edc..a4b3cd37 100644 --- a/doc/splitjoin.txt +++ b/doc/splitjoin.txt @@ -1293,6 +1293,17 @@ for the `sh` and `zsh` filetypes. echo "one" echo "two" < +If the line is not made up of semicolon-separated commands, it gets broken up +with a backslash at the cursor position, for example with the cursor on the +pipe: +> + echo "one" | wc -c + + echo "one" \ + | wc -l +< +If there is a broken line like that, joining should always join it first, +before trying anything else. ============================================================================== TEX *splitjoin-tex* diff --git a/ftplugin/sh/splitjoin.vim b/ftplugin/sh/splitjoin.vim index 053ed1a7..1a1394da 100644 --- a/ftplugin/sh/splitjoin.vim +++ b/ftplugin/sh/splitjoin.vim @@ -1,7 +1,9 @@ let b:splitjoin_split_callbacks = [ \ 'sj#sh#SplitBySemicolon', + \ 'sj#sh#SplitWithBackslash', \ ] let b:splitjoin_join_callbacks = [ + \ 'sj#sh#JoinBackslashedLine', \ 'sj#sh#JoinWithSemicolon', \ ] diff --git a/spec/plugin/sh_spec.rb b/spec/plugin/sh_spec.rb index 88ac7939..9db32e86 100644 --- a/spec/plugin/sh_spec.rb +++ b/spec/plugin/sh_spec.rb @@ -3,7 +3,12 @@ describe "sh" do let(:filename) { 'test.sh' } - describe "splitjoining by semicolon" do + before :each do + vim.set(:expandtab) + vim.set(:shiftwidth, 2) + end + + describe "by semicolon" do specify "simple case" do set_file_contents <<~EOF echo "one"; echo "two" @@ -51,5 +56,46 @@ EOF end end -end + describe "with backslash" do + specify "simple case" do + set_file_contents <<~EOF + echo "one" | wc -c + EOF + + vim.search('|') + split + + assert_file_contents <<~EOF + echo "one" \\ + | wc -c + EOF + + join + + assert_file_contents <<~EOF + echo "one" | wc -c + EOF + end + + specify "between words, finds closest non-whitespace forward" do + set_file_contents <<~EOF + echo "one" | wc -c + EOF + + vim.search(' w') + split + + assert_file_contents <<~EOF + echo "one" | \\ + wc -c + EOF + + join + + assert_file_contents <<~EOF + echo "one" | wc -c + EOF + end + end +end