aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2018-07-20 20:32:27 +1200
committerTom Ryder <tom@sanctum.geek.nz>2018-07-20 20:32:27 +1200
commit61e75533311456b651b8ad47632a9d833d80ecc5 (patch)
treea48a1ceb90229e9752fe8fdd890ff00318854f80
parentMerge branch 'release/v1.0.0' (diff)
parentBump VERSION (diff)
downloadvim-strip-trailing-whitespace-61e75533311456b651b8ad47632a9d833d80ecc5.tar.gz
vim-strip-trailing-whitespace-61e75533311456b651b8ad47632a9d833d80ecc5.zip
Merge branch 'release/v2.0.0'v2.0.0
* release/v2.0.0: Bump VERSION Overhaul for new version
-rw-r--r--README.md7
-rw-r--r--VERSION2
-rw-r--r--doc/strip_trailing_whitespace.txt27
-rw-r--r--plugin/strip_trailing_whitespace.vim152
4 files changed, 107 insertions, 81 deletions
diff --git a/README.md b/README.md
index 4ea75b4..abddc14 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
strip\_trailing\_whitespace.vim
===============================
-This plugin provides a mapping target with the author's approach to stripping
+This plugin provides a user command with the author's approach to stripping
trailing whitespace from an entire buffer, including removing empty or
whitespace-only lines at the end of the buffer, without making command noise
and without moving the cursor from its current position.
@@ -9,15 +9,14 @@ and without moving the cursor from its current position.
This is a very commonly written and implemented plugin, but I wrote my own
because I could not find a plugin that did this in exactly the way I wanted:
-- Provide a `<Plug>` mapping
+- Accept an optional range
- Strip trailing lines as well as trailing spaces
-- Accurately report what was changed
+- Report what was changed, accurately
- Work with even very old Vim (>=6.0)
- Work with a single `undo`
- Don't move the cursor
- Don't change the search pattern
- Don't define an `autocmd`
-- Don't define a user command
- Don't force a key mapping
- Don't define a global function
diff --git a/VERSION b/VERSION
index 3eefcb9..227cea2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.0
+2.0.0
diff --git a/doc/strip_trailing_whitespace.txt b/doc/strip_trailing_whitespace.txt
index 8ee64f3..c29b664 100644
--- a/doc/strip_trailing_whitespace.txt
+++ b/doc/strip_trailing_whitespace.txt
@@ -1,8 +1,8 @@
-*strip_trailing_whitespace.txt* For Vim version 6.0 Last change: 2018 June 27
+*strip_trailing_whitespace.txt* For Vim version 6.0 Last change: 2018 Jul 20
DESCRIPTION *strip_trailing_whitespace*
-This plugin provides a mapping target with the author's approach to stripping
+This plugin provides a user command with the author's approach to stripping
trailing whitespace from an entire buffer, including removing empty or
whitespace-only lines at the end of the buffer, without making command noise
and without moving the cursor from its current position.
@@ -10,31 +10,30 @@ and without moving the cursor from its current position.
This is a very commonly written and implemented plugin, but I wrote my own
because I could not find a plugin that did this in exactly the way I wanted:
-- Provide a |<Plug>| mapping
+- Accept an optional range
- Strip trailing lines as well as trailing spaces
-- Accurately report what was changed
+- Report what was changed, accurately
- Work with even very old Vim (>=6.0)
- Work with a single |undo|
- Don't move the cursor
- Don't change the search pattern
- Don't define an |autocmd|
-- Don't define a user command
- Don't force a key mapping
- Don't define a global function
REQUIREMENTS *strip_trailing_whitespace-requirements*
-This plugin is only available if 'compatible' is not set.
+This plugin is only available if 'compatible' is not set. It also requires the
+|+user_commands| feature.
-MAPPINGS *strip_trailing_whitespace-mappings*
+COMMANDS *strip_trailing_whitespace-commands*
+
+ *:StripTrailingWhitespace*
+Strip trailing space appropriately for the range of lines selected, defaulting
+to the entire buffer. Remove all horizontal whitespace from the end of each
+line. If the last line of the range is also the last line of the buffer, strip
+trailing blank or whitespace-only lines as well.
- *<Plug>(StripTrailingWhitespace)*
-The single mapping target provided is |<Plug>(StripTrailingWhitespace)|,
-mappable in any mode. There is no default key mapping to the target; you
-should define this yourself in your |vimrc|. For example:
->
- nmap <Leader>x <Plug>(StripTrailingWhitespace)
-<
AUTHOR *strip_trailing_whitespace-author*
Written and maintained by Tom Ryder <tom@sanctum.geek.nz>.
diff --git a/plugin/strip_trailing_whitespace.vim b/plugin/strip_trailing_whitespace.vim
index de08fae..75438d9 100644
--- a/plugin/strip_trailing_whitespace.vim
+++ b/plugin/strip_trailing_whitespace.vim
@@ -1,6 +1,7 @@
"
-" strip_trailing_whitespace.vim: User-defined key mapping to strip trailing
-" whitespace in the whole document.
+" strip_trailing_whitespace.vim: User command to strip both horizontal and
+" vertical whitespace in a buffer, with optional range, reporting both
+" accurately and restoring the cursor afterwards.
"
" Author: Tom Ryder <tom@sanctum.geek.nz>
" License: Same as Vim itself
@@ -8,88 +9,115 @@
if exists('g:loaded_strip_trailing_whitespace') || &compatible
finish
endif
-if v:version < 600
+if !has('user_commands') || v:version < 600
finish
endif
let g:loaded_strip_trailing_whitespace = 1
-" Define function for stripping whitespace
-function! s:StripTrailingWhitespace()
+" Wrapper function to strip both horizontal and vertical trailing whitespace,
+" return the cursor to its previous position, and report changes
+function s:Strip(start, end) abort
- " Line number of last line that had non-whitespace characters on it
- let l:cutoff = 1
+ " Save cursor position
+ let l:line = line('.')
+ let l:col = col('.')
- " Tracking lines trimmed between non-whitespace lines and then totalling
- let l:trimmed_buffer = 0
- let l:trimmed = 0
+ " Strip horizontal space
+ let l:horizontal = s:StripHorizontal(a:start, a:end)
+ let l:msg = l:horizontal.' trimmed'
+ let l:changed = l:horizontal > 0
- " Line number of the file's last line
- let l:last = line('$')
+ " If we're going to the end, strip vertical space
+ if a:end == line('$')
+ let l:vertical = s:StripVertical()
+ let l:msg = l:msg.', '.l:vertical.' deleted'
+ let l:changed = l:changed || l:vertical > 0
+ endif
- " Iterate over the lines
- let l:li = 1
- while l:li <= l:last
+ " Return the cursor
+ call s:Cursor(l:line, l:col)
- " Get the line text
- let l:line = getline(l:li)
+ " Report what changed
+ echomsg l:msg
- " If the current line contains trailing whitespace, substitute it out
- if l:line =~# '\s\+$'
- call setline(l:li, substitute(l:line, '\s\+$', '', ''))
- let l:trimmed_buffer = l:trimmed_buffer + 1
- endif
+ " Return whether anything changed
+ return l:changed
+
+endfunction
- " If this line has any non-whitespace characters on it, update our cutoff
- " point using its index, and push the trimmed lines we've counted since
- " the last non-whitespace line onto the trimmed total
- if l:line =~# '\S' || l:last == 1
- let l:cutoff = l:li
- let l:trimmed = l:trimmed + l:trimmed_buffer
- let l:trimmed_buffer = 0
+" Strip horizontal trailing whitespace, return the number of lines changed
+function s:StripHorizontal(start, end) abort
+
+ " Start a count of lines trimmed
+ let l:count = 0
+
+ " Iterate through buffer
+ let l:num = 1
+ while l:num <= line('$')
+
+ " If the line has trailing whitespace, strip it off and bump the count
+ let l:line = getline(l:num)
+ if l:line =~# '\s\+$'
+ call setline(l:num, substitute(l:line, '\s*$', '', ''))
+ let l:count = l:count + 1
endif
- " Increment the line counter for the next iteration
- let l:li = l:li + 1
+ " Bump for next iteration
+ let l:num = l:num + 1
endwhile
- " If the last non-whitespace line was before the last line proper, we can
- " delete all lines after it
- let l:deleted = 0
- if l:cutoff < l:last
-
- " Get the current line and column so we can return to it
- " (Yes I know about winsaveview() and winrestview(); I want this to work
- " even on very old versions of Vim if possible)
- let l:cursor_line = line('.')
- let l:cursor_col = col('.')
-
- " Delete the rest of the lines, which will move the cursor
- silent execute l:cutoff + 1 . ',$ delete _'
-
- " Return the cursor to the saved position (Vim 6.0 fallback)
- if exists('*cursor')
- call cursor(l:cursor_line, l:cursor_col)
- else
- execute 'normal! '
- \ . l:cursor_line . 'G'
- \ . l:cursor_col . '|'
+ " Return the number of lines trimmed
+ return l:count
+
+endfunction
+
+" Strip trailing vertical whitespace, return the number of lines changed
+function s:StripVertical() abort
+
+ " Store the number of the last line we found with non-whitespace characters
+ " on it; start at 1 because even if it's empty it's never trailing
+ let l:eof = 1
+
+ " Iterate through buffer
+ let l:num = 1
+ while l:num <= line('$')
+
+ " If the line has any non-whitespace characters in it, update our pointer
+ " to the end of the file text
+ let l:line = getline(l:num)
+ if l:line =~# '\S'
+ let l:eof = l:num
endif
- " Record the number of lines deleted
- let l:deleted = l:last - l:cutoff
+ " Bump for next iteration
+ let l:num = l:num + 1
+ endwhile
+
+ " Get the number of lines to delete; if there are any, build a range and
+ " remove them with :delete, suppressing its normal output (we'll do it)
+ let l:count = line('$') - l:eof
+ if l:count
+ let l:range = (l:eof + 1).',$'
+ silent execute l:range.'delete'
endif
- " Print what we did
- echomsg l:trimmed . ' trimmed, ' . l:deleted . ' deleted'
+ " Return the number of lines deleted
+ return l:count
- " Return the number of affected lines
- return l:trimmed + l:deleted
+endfunction
+" Position the cursor; use cursor() if we have it, :normal if not (Vim 6.0)
+function s:Cursor(line, col) abort
+ if exists('*cursor')
+ return cursor(a:line, a:col)
+ else
+ execute 'normal! '.a:line.'G'.a:col.'|'
+ return 1
+ endif
endfunction
-" Create mapping proxy to the function just defined
-nnoremap <silent> <unique>
- \ <Plug>(StripTrailingWhitespace)
- \ :<C-U>call <SID>StripTrailingWhitespace()<CR>
+" User command for the above
+command! -range=% StripTrailingWhitespace
+ \ call <SID>Strip(<line1>, <line2>)