Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Documentation

  • Loading branch information...
commit 619a851f4b7ac1f1975f131fbcd75928822be81f 1 parent 65ff89a
@AndrewRadev authored
Showing with 107 additions and 24 deletions.
  1. +28 −6 autoload/whitespaste.vim
  2. +79 −18 doc/whitespaste.txt
View
34 autoload/whitespaste.vim
@@ -8,12 +8,13 @@ function! whitespaste#Paste(normal_command)
endif
endfunction
-" Note: clean up after the text, then before the text to avoid problems with
-" changing line numbers lower in the buffer due to changes upper in the the
-" buffer.
+" Note: clean up after the text first, then before the text to avoid problems
+" with changing line numbers lower in the buffer due to changes upper in the
+" the buffer.
function! whitespaste#PasteLinewise(normal_command)
call s:Paste(a:normal_command)
+ " Fetch the necessary information
let first_pasted_line = line("'[")
let last_pasted_line = line("']")
let target_area_start = prevnonblank(first_pasted_line - 1)
@@ -25,6 +26,7 @@ function! whitespaste#PasteLinewise(normal_command)
let target_area_end = line('$') + 1
endif
+ " Create containers with the current state of the paste
let top = {
\ 'target_line': target_area_start,
\ 'target_text': getline(target_area_start),
@@ -39,6 +41,7 @@ function! whitespaste#PasteLinewise(normal_command)
\ 'pasted_text': getline(pasted_area_end)
\ }
+ " Accumulate the user-provided definitions
let definitions = {'top': [], 'bottom': []}
if exists('b:whitespaste_linewise_definitions')
call extend(definitions.top, b:whitespaste_linewise_definitions.top)
@@ -50,7 +53,8 @@ function! whitespaste#PasteLinewise(normal_command)
try
let saved_cursor = getpos('.')
- for definition in get(definitions, 'bottom', {})
+ " Clean up bottom area and adjust for resulting changes
+ for definition in get(definitions, 'bottom')
let [success, delta] = s:HandleDefinition(bottom, definition, pasted_area_end, target_area_end)
if success
let target_area_end += delta
@@ -58,7 +62,8 @@ function! whitespaste#PasteLinewise(normal_command)
endif
endfor
- for definition in get(definitions, 'top', {})
+ " Clean up top area and adjust for resulting changes
+ for definition in get(definitions, 'top')
let [success, delta] = s:HandleDefinition(top, definition, target_area_start, pasted_area_start)
if success
let pasted_area_start += delta
@@ -68,7 +73,7 @@ function! whitespaste#PasteLinewise(normal_command)
endif
endfor
- " Restore [ and ] marks
+ " Restore [ and ] marks to the best of our ability
let start_pos = getpos("'[")
let start_pos[1] = target_area_start + 1
call setpos("'[", start_pos)
@@ -81,6 +86,11 @@ function! whitespaste#PasteLinewise(normal_command)
endtry
endfunction
+" Checks if the given a:definition matches the actual state of the paste in
+" the a:actual variable. If it does, performs the action given in the
+" definition and returns a successful result.
+"
+" Returns two values: [success, line_change].
function! s:HandleDefinition(actual, definition, start, end)
let [actual, definition, start, end] = [a:actual, a:definition, a:start, a:end]
@@ -89,6 +99,8 @@ function! s:HandleDefinition(actual, definition, start, end)
let definition.target_line = line('$') + 1
endif
+ " Return failure if the given definition matches doesn't match the actual
+ " state of the paste
if has_key(definition, 'target_line') && actual.target_line != definition.target_line
return [0, 0]
endif
@@ -102,6 +114,7 @@ function! s:HandleDefinition(actual, definition, start, end)
return [0, 0]
endif
+ " The definition matches, so decide what to do
if has_key(definition, 'compress_blank_lines')
let line_change = whitespaste#CompressBlankLines(start, end, definition.compress_blank_lines)
elseif has_key(definition, 'blank_lines')
@@ -123,6 +136,8 @@ function! whitespaste#PasteBlockwise(normal_command)
call s:Paste(a:normal_command)
endfunction
+" Sets the blank lines between the given a:start and a:end to be at most
+" a:line_count in number. Only decreases whitespace, never increases it.
function! whitespaste#CompressBlankLines(start, end, line_count)
let [start, end, line_count] = [a:start, a:end, a:line_count]
let existing_line_count = (end - start) - 1
@@ -134,6 +149,8 @@ function! whitespaste#CompressBlankLines(start, end, line_count)
endif
endfunction
+" Sets the blank lines between the given a:start and a:end to be exactly
+" a:line_count in number. Could increase or decrease whitespace.
function! whitespaste#SetBlankLines(start, end, line_count)
let [start, end, line_count] = [a:start, a:end, a:line_count]
let existing_line_count = (end - start) - 1
@@ -162,6 +179,9 @@ function! whitespaste#SetBlankLines(start, end, line_count)
endif
endfunction
+" Note: the purpose of storing and restoring of the default register is to
+" avoid the user having to worry about v:register when overriding the paste
+" commands.
function! s:Paste(command)
let default_register = s:DefaultRegister()
let original_value = getreg(default_register, 1)
@@ -174,6 +194,8 @@ function! s:Paste(command)
call setreg(default_register, original_value, original_type)
endfunction
+" The default register that's used when pasting depends on the 'clipboard'
+" option.
function! s:DefaultRegister()
if &clipboard =~ 'unnamedplus'
return '+'
View
97 doc/whitespaste.txt
@@ -31,25 +31,54 @@ directory: plugin, autoload, doc.
==============================================================================
USAGE *whitespaste-usage*
-This plugin provides two <Plug> mappings, <Plug>WhitespasteBefore and
-<Plug>WhitespasteAfter that are meant to be used as replacements to the |P| and
-|p| mappings respectively. To override the built-ins directly:
+This plugin remaps the standard |p| and |P| mappings to enhance their
+functionality. When pasting, it compresses all blank lines that result from
+the paste to a single one. That way, even if you copy any leftover whitespace,
+it'll be neatly trimmed to just one line. This takes effect only for linewise
+pasting, since it's not entirely clear what the behaviour should be for
+characterwise and blockwise pasting.
+
+If you don't want to clobber your default |p| and |P| mappings, you can make
+whitespaste use different ones by setting two predefined variables:
>
- nmap P <Plug>WhitespasteBefore
- nmap p <Plug>WhitespasteAfter
+ let g:whitespaste_before_mapping = ',P'
+ let g:whitespaste_after_mapping = ',p'
<
-If you want to assign these to other keys, just map them to whatever you like:
+If you need more fine-grained control, you can disable mappings altogether by
+setting both of these variables to empty strings. You can then use the three
+provided <Plug> mappings for your purposes. For example:
>
- nmap <leader>P <Plug>WhitespasteBefore
- nmap <leader>p <Plug>WhitespasteAfter
+ let g:whitespaste_before_mapping = ''
+ let g:whitespaste_after_mapping = ''
+
+ nmap ,P <Plug>WhitespasteBefore
+ nmap ,p <Plug>WhitespasteAfter
+
+ xmap ,P <Plug>WhitespasteVisual
+ xmap ,p <Plug>WhitespasteVisual
<
+The plugin also takes care of special cases like pasting functions/methods,
+if-clauses and so on. Currently, these special cases work only with ruby and
+vimscript, but see below in |whitespaste-extending| to find out how you can
+extend the plugin for a different language or change it to fit your own coding
+style.
+
+Whitespaste can play well with other plugins like vim-pasta. The underlying
+paste command that is being executed is available as a global variable and can
+be changed. For example, here's how you could combine whitespaste with vim-pasta:
+>
+ " first, disable vim-pasta's mappings
+ let g:pasta_enabled_filetypes = []
-The plugin differs from standard pasting by compressing all whitespace that
-results in a linewise paste to a single line. It also takes care of special
-cases like pasting functions/methods, if-clauses and so on. Currently, these
-special cases work only with ruby and vimscript, but see below in
-|whitespaste-extending| to find out how you can extend the plugin for a
-different language or change it to fit your own coding style.
+ " then, set whitespaste's paste commands to execute vim-pasta's mappings
+ let g:whitespaste_paste_before_command = "normal \<Plug>BeforePasta"
+ let g:whitespaste_paste_after_command = "normal \<Plug>AfterPasta"
+ let g:whitespaste_paste_visual_command = "normal gv\<Plug>VisualPasta"
+<
+It's important to note that the plugin will take care of adjusting registers,
+so that you don't have to compensate for that in the command your provide. For
+example, even if you set the command to "normal! p", you could still use
+whitespaste with different registers and it would work correctly.
==============================================================================
@@ -169,16 +198,48 @@ example, remove whitespace at the top and bottom of the buffer, and compress
all other pasting operations to only one blank line. There are also specific
definitions for ruby and vimscript.
+
==============================================================================
SETTINGS *whitespaste-settings*
-TODO
+ *g:whitespaste_before_mapping*
+ *g:whitespaste_after_mapping*
+>
+ let g:whitespaste_before_mapping = ',P'
+ let g:whitespaste_after_mapping = ',p'
+<
+
+Default values: P, p
+These variables contain the mappings you need to enter to paste with
+whitespaste. By default, they're "P" and "p" respectively, so they override
+the built-in mappings. Set them to empty strings to avoid setting any mappings
+by the plugin.
-==============================================================================
-INTERNALS *whitespaste-internals*
+ *g:whitespaste_paste_before_command*
+ *g:whitespaste_paste_after_command*
+ *g:whitespaste_paste_visual_command*
+>
+ let g:whitespaste_paste_before_command = 'normal! ]P'
+ let g:whitespaste_paste_after_command = 'normal! ]p'
+ let g:whitespaste_paste_visual_command = 'normal! gvp'
+<
+
+Default values:
+ g:whitespaste_paste_before_command == 'normal! P'
+ g:whitespaste_paste_after_command == 'normal! p'
+ g:whitespaste_paste_visual_command == 'normal! gvp'
+
+These variables allow customization of the underlying paste operation. You can
+set them to any command you like. To perform a mapping, you should probably
+use |normal|, so if you're unfamiliar with it, please read the related help
+files. In most cases, "normal!" should be preferred in order to avoid infinite
+recursion.
+
+Note that the visual command is not executed in a visual mode context, so you
+should either use |gv| to enter the last visual mode, or rely on the '<,'>
+range in your command.
-TODO
==============================================================================
ISSUES *whitespaste-issues*
Please sign in to comment.
Something went wrong with that request. Please try again.