added wrap mode detect via line sampling; now ignores wm

This commit is contained in:
Reed Esau
2014-01-14 23:37:09 -07:00
parent 44fde3aba7
commit d634989c87
3 changed files with 95 additions and 54 deletions

View File

@@ -16,9 +16,9 @@ smooth the path to writing prose.
* For editing files in _text_, _markdown_, _textile_, and other
prose-oriented file types
* Agnostic on soft line wrapping _versus_ hard line breaks, supporting
* Agnostic on soft line wrap _versus_ hard line breaks, supporting
both
* Auto-detects wrap mode via modeline if present
* Auto-detects wrap mode via modeline and sampling
* Adjusts navigation key mappings to suit the wrap mode
* Creates undo points on common punctuation
* When using hard line breaks, enables autoformat while inserting text
@@ -61,7 +61,7 @@ the basics of Vim._
## Configuration
### Hard line breaks or soft line wrapping?
### Hard line breaks or soft line wrap?
Coders will have the most experience with the former, and writers the
latter. But whatever your background, chances are that you must contend
@@ -82,16 +82,16 @@ augroup END
```
In the example above, for files of type `markdown` and `textile`, this
plugin will auto-detect the wrapping approach, with `hard` as the default.
But for files of type `text`, it will *always* initialize with hard line
break mode.
plugin will auto-detect the line wrap approach, with `hard` as the
default. But for files of type `text`, it will *always* initialize with
hard line break mode.
### Commands
Because auto-detect might not work as intended, you can invoke a command
to set the behavior for the current buffer:
* `SoftPencil` - mode for soft line wrapping
* `SoftPencil` - mode for soft line wrap
* `HardPencil` - mode for hard line breaks
* `DropPencil` - removes navigation mappings and restores buffer to global settings
* `TogglePencil` - if off, enables with detection; if on, turns off
@@ -111,7 +111,7 @@ _This autoformat feature affects **HardPencil** mode only._
When in **HardPencil** mode, Vims autoformat feature will be enabled by
default in Insert mode and can offer many of the same benefits as soft
line wrapping. But autoformat will cause havoc when editing anything but
line wrap. But autoformat will cause havoc when editing anything but
paragraphs of words, such as a code block or table. In these cases you
will need to disable it, at least temporarily, via a command:
@@ -198,42 +198,73 @@ a hard break. If you wish to retain the default Vim behavior, set the
let g:pencil#cursorwrap = 1 " 0=disable, 1=enable
```
## Auto-detection via modeline
## Auto-detecting wrap mode
Will the wrapping mode be detected accurately? Maybe. But you can improve
its chances by giving it a hint.
If you provided no explicit wrap mode during initialization, _pencil_ will
attempt to automatically detect the wrap mode.
At the bottom of this document is a strange code:
It will first look for a `textwidth` (or `tw`) specified in a modeline.
Failing that _pencil_ will then sample lines from the start of the file.
### Detect via modeline
Will the wrap mode be detected accurately? Maybe. But you can improve its
chances by giving it an explicit hint.
At the bottom of this document is a odd-looking code:
```
<!-- vim: set tw=74 :-->
```
This is a modeline that tells Vim to run the following command upon
loading this file into a buffer:
loading the file into a buffer:
```vim
:set textwidth=74
```
Thats a strong hint to this plugin that we should assume hard line
endings, regardless of whether or not soft wrapping is the default editing
mode for files of type markdown.
If its `0`, then pencil assumes you want soft line wrapping.
Thats a strong hint to _pencil_ that it should assume hard line breaks,
regardless of whether or not soft line wrap is the default editing mode
for files of type markdown.
```
<!-- vim: set tw=0 :-->
```
For more details:
```vim
:help modeline
```
If textwidth is `0` as shown above, then _pencil_ assumes you want soft
line wrap.
Note that even if the modelines feature is disabled (such as for security
reasons) the textwidth may nevertheless be set by this plugin.
reasons) the textwidth will still be set by this plugin.
### Detect via sampling
If no modeline with a textwidth is found, _pencil_ will sample the initial
lines from the file looking for excessively-long lines.
There are two settings you can add to your `.vimrc` to tweak this behavior.
The maximum number of lines to sample from the start of the file:
```vim
let g:pencil#softDetectSample = 10
```
Set that value to `0` to disable detection via line sampling.
When the number of bytes on a sampled line per exceeds this next value,
then _pencil_ assumes soft line wrap.
```vim
let g:pencil#softDetectThreshold = 130
```
If no such lines found, _pencil_ falls back to the default:
```vim
let g:pencil#wrapModeDefault = 'hard' " or 'soft'
```
## See also
@@ -241,7 +272,6 @@ reasons) the textwidth may nevertheless be set by this plugin.
* [Vim Training Class - Basic motions and commands](https://www.youtube.com/watch?v=Nim4_f5QUxA) - video tutorial by Shawn Biddle
* [Vim for Writers](http://therandymon.com/woodnotes/vim-for-writers/vimforwriters.html) - guide to the basics geared to writers
* [Vim-related books](http://iccf-holland.org/click5.html) - collection of books on learning Vim
* [pencil at vim.org](http://www.vim.org/scripts/script.php?script_id=4824)
If you like this plugin, you might like these others from the same author:

View File

@@ -15,30 +15,32 @@ let s:WRAP_MODE_HARD = 1
let s:WRAP_MODE_SOFT = 2
" Wrap-mode detector
" attempt to determine user's intent from modeline
" Scan lines at end and beginning of file to determine the wrap mode.
" Modelines has priority over long lines found.
function! s:detect_mode() abort
let b:max_textwidth = -1
let b:min_textwidth = 9999
let b:max_wrapmargin = -1
let b:min_wrapmargin = 9999
let b:max_textwidth = -1 " assume no relevant modeline
call s:doModelines()
if b:max_textwidth == -1 &&
\ b:min_textwidth == 9999 &&
\ b:max_wrapmargin == -1 &&
\ b:min_wrapmargin == 9999
" no relevant modeline params present
return s:WRAP_MODE_DEFAULT
elseif b:max_textwidth <= 0 && b:max_wrapmargin <= 0
" no textwidth or wrapmargin were gt 0
if b:max_textwidth == 0
" modeline(s) found only with zero textwidth, so it's soft wrapped
return s:WRAP_MODE_SOFT
elseif b:min_textwidth > 0 || b:min_wrapmargin > 0
" at least one textwidth or wrapmargin was gt 0
return s:WRAP_MODE_HARD
else
" unsure what to do!
return s:WRAP_MODE_DEFAULT
endif
if b:max_textwidth > 0
" modelines(s) found with positive textwidth, so hard line breaks
return s:WRAP_MODE_HARD
endif
" scan initial lines in an attempt to detect long lines
for l:line in getline(1, g:pencil#softDetectSample)
if len(l:line) > g:pencil#softDetectThreshold
return s:WRAP_MODE_SOFT
endif
endfor
" punt
return s:WRAP_MODE_DEFAULT
endfunction
function! pencil#setAutoFormat(mode)
@@ -140,7 +142,10 @@ function! pencil#init(...) abort
" clean out stuff we likely don't want
setlocal formatoptions-=2
setlocal formatoptions-=v
setlocal formatoptions-=w " trailing whitespace continues paragraph (will enable in insert mode)
" trailing whitespace continues paragraph
" makes autoformat behave oddly where spaces aren't present
setlocal formatoptions-=w
else
setlocal autoindent< noautoindent<
setlocal list< nolist<
@@ -224,15 +229,6 @@ fun! s:doOne(item) abort
if l:matches[1] =~ 'textwidth\|tw'
if l:matches[2] > b:max_textwidth
let b:max_textwidth = l:matches[2]
elseif l:matches[2] < b:min_textwidth
let b:min_textwidth = l:matches[2]
endif
endif
if l:matches[1] =~ 'wrapmargin\|wm'
if l:matches[2] > b:max_wrapmargin
let b:max_wrapmargin = l:matches[2]
elseif l:matches[2] < b:min_wrapmargin
let b:min_wrapmargin = l:matches[2]
endif
endif
endif
@@ -254,6 +250,8 @@ fun! s:doModeline(line) abort
endif
endfun
" sample lines for detection, capturing both
" modeline(s) and max line length
" Hat tip to https://github.com/ciaranm/securemodelines
fun! s:doModelines() abort
if line("$") > &modelines

View File

@@ -41,6 +41,19 @@ if !exists('g:pencil#cursorwrap')
let g:pencil#cursorwrap = 1
endif
if !exists('g:pencil#softDetectSample')
" if no modeline, read as many as this many lines at
" start of file in attempt to detect at least one line
" whose byte count exceeds g:pencil#softDetectThreshold
let g:pencil#softDetectSample = 10
endif
if !exists('g:pencil#softDetectThreshold')
" if the byte count of at least one sampled line exceeds
" this number, then pencil assumes soft line wrapping
let g:pencil#softDetectThreshold = 130
endif
" # Commands
command -nargs=0 HardPencil call pencil#init({'wrap': 'hard'})
command -nargs=0 SoftPencil call pencil#init({'wrap': 'soft'})