Skip to content

Commit

Permalink
Blacklist (and whitelist) config by file type
Browse files Browse the repository at this point in the history
  • Loading branch information
Reed Esau committed Sep 7, 2015
1 parent 290b087 commit f89a3ac
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 79 deletions.
60 changes: 33 additions & 27 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ smooth the path to writing prose.
deletion via line `<C-U>` and word `<C-W>`
* When using hard line breaks, _pencil_ enables Vim’s autoformat while
inserting text, except for tables and code blocks where you won’t want
it
it (**NEW: blacklisting now based on filetype**)
* Buffer-scoped configuration (with a few minor exceptions, _pencil_ preserves
your global settings)
* Support for Vim’s Conceal feature to hide markup defined by Syntax plugins
Expand Down Expand Up @@ -101,8 +101,6 @@ Plugin 'reedes/vim-pencil'
:PluginInstall
```

For Vundle version < 0.10.2, replace `Plugin` with `Bundle` above.

#### Plug

Add to your `.vimrc` and save:
Expand Down Expand Up @@ -429,7 +427,7 @@ augroup END
Alternatives include `after/ftplugin` modules as well as refactoring initialization
statements into a function.

### Autoformat blacklisting
### Autoformat blacklisting (and whitelisting)

_The ‘autoformat’ feature affects *HardPencil* (hard line break) mode
only._
Expand All @@ -443,31 +441,39 @@ won’t need to do this.
_pencil_ will detect the syntax highlight group at the cursor position to
determine whether or not autoformat should be activated.

If autoformat is on, it will be activated at the time you enter Insert
mode provided that the syntax highlighting group at the cursor position is
_not_ in the blacklist. The current blacklist is:
If you haven’t explicitly disabled autoformat, it will be activated at
the time you enter Insert mode provided that the syntax highlighting
group at the cursor position is _not_ in the blacklist.

Blacklists are now declared by file type. The default blacklists (and
whitelists) are declared in the `plugin/pencil.vim` module. Here’s an
excerpt showing the configuration for the ‘markdown’ file type:

```vim
let g:pencil#autoformat_blacklist = [
\ 'markdown(Code|H[0-9]|Url|IdDeclaration|Link|Rule|Highlight[A-Za-z0-9]+)',
\ 'mkd(Code|Rule|Delimiter|Link|ListItem|IndentCode)',
\ 'htmlH[0-9]',
\ 'markdown(FencedCodeBlock|InlineCode)',
\ 'mmdTable[A-Za-z0-9]*',
\ 'txtCode',
\ 'rst(CodeBlock|Directive|LiteralBlock|Sections)',
\ 'tex(BeginEndName|Delimiter|DocType|InputFile|Math|RefZone|Title)',
\ 'texSection$',
\ 'asciidoc(AttributeList|ListLabel|Literal|SideBar|Source|Sect[0-9])',
\ 'asciidoc[A-Za-z]*(Block|Macro|Title)',
\ ]
```

_WARNING: the implementation of this blacklist will be changing in the
future._

You can override this in your `.vimrc`. Additions to defaults with good
use cases are welcome.
let g:pencil#autoformat_config = {
\ 'markdown': {
\ 'black': [
\ 'markdown(Code|H[0-9]|Url|IdDeclaration|Link|Rule|Highlight[A-Za-z0-9]+)',
\ 'htmlH[0-9]',
\ 'markdown(FencedCodeBlock|InlineCode)',
\ 'mmdTable[A-Za-z0-9]*',
\ ],
\ 'white': [
\ 'markdown(Code|Link)',
\ ],
\ },
[snip]
\ }
```

For example, if editing a file of type ‘markdown’ and you enter Insert
mode from inside a `markdownFencedCodeBlock` highlight group, then Vim’s
autoformat will _not_ be enabled.

The whitelist can override the blacklist and allow Vim’s autoformat to be
enabled if text that would normally be blacklisted doesn’t dominate the
entire line. This allows autoformat to work with `inline` snippets of
code or links.

### Auto-detecting wrap mode

Expand Down
53 changes: 30 additions & 23 deletions autoload/pencil.vim
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,18 @@ fun! s:imap(preserve_completion, key, icmd) abort
endf

fun! s:maybe_enable_autoformat() abort
" don't enable autoformat if in a code block or table
" don't enable autoformat if in a blacklisted code block or table,
" allowing for reprieve via whitelist in certain cases

let l:af_cfg = get(g:pencil#autoformat_config, &ft, {})
let l:black = get(l:af_cfg, 'black', [])
let l:white = get(l:af_cfg, 'white', [])
let l:has_black_re = len(l:black) > 0
let l:has_white_re = len(l:white) > 0
let l:black_re = l:has_black_re ? '\v(' . join( l:black, '|') . ')' : ''
let l:white_re = l:has_white_re ? '\v(' . join( l:white, '|') . ')' : ''
let l:enforce_previous_line = get(l:af_cfg, 'enforce-previous-line', 0)

let l:okay_to_enable = 1
let l:line = line('.')
let l:col = col('.')
Expand Down Expand Up @@ -88,21 +99,21 @@ fun! s:maybe_enable_autoformat() abort
endw
en
" enforce blacklist by scanning for syntax matches
for l:sid in l:stack
if match(synIDattr(l:sid, 'name'),
\ g:pencil#autoformat_blacklist_re) >= 0
let l:okay_to_enable = 0
"echohl WarningMsg
"echo 'hit blacklist line=' . l:line . ' col=' . l:col .
" \ ' name=' . synIDattr(l:sid, 'name')
"echohl NONE
break
en
endfo
" enforce whitelist by detecting inline `markup` for
" which we DO want autoformat to be enabled (e.g.,
" tpope's markdownCode)
if !l:okay_to_enable
if l:has_black_re
for l:sid in l:stack
if match(synIDattr(l:sid, 'name'), l:black_re) >= 0
let l:okay_to_enable = 0
"echohl WarningMsg
"echo 'hit blacklist line=' . l:line . ' col=' . l:col .
" \ ' name=' . synIDattr(l:sid, 'name')
"echohl NONE
break
en
endfo
en
" enforce whitelist by detecting inline `markup` for which we DO want
" autoformat to be enabled (e.g., tpope's markdownCode)
if l:has_white_re && !l:okay_to_enable
" one final check for an empty stack at the start and end of line,
" either of which greenlights a whitelist check
if !l:found_empty
Expand All @@ -113,23 +124,19 @@ fun! s:maybe_enable_autoformat() abort
en
if l:found_empty
for l:sid in l:stack
if match(synIDattr(l:sid, 'name'),
\ g:pencil#autoformat_inline_whitelist_re) >= 0
if match(synIDattr(l:sid, 'name'), l:white_re) >= 0
let l:okay_to_enable = 1
break
en
endfo
en
en
" disallow enable if start of previous line is in blacklist,
" (To avoid problem of autowrap screwing up adding a new item
" to a list.)
if l:okay_to_enable && l:line > 1
if l:has_black_re && l:enforce_previous_line && l:okay_to_enable && l:line > 1
let l:prev_stack = synstack(l:line - 1, 1)
for l:sid in l:prev_stack
if len(l:sid) > 0 &&
\ match(synIDattr(l:sid, 'name'),
\ g:pencil#autoformat_blacklist_re) >= 0
\ match(synIDattr(l:sid, 'name'), l:black_re) >= 0
let l:okay_to_enable = 0
break
en
Expand Down
77 changes: 48 additions & 29 deletions plugin/pencil.vim
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ if !exists('g:pencil#autoformat')
let g:pencil#autoformat = 1
en

if !exists('g:pencil#autoformat_blacklist')
if !exists('g:pencil#autoformat_config')
" do not engage autoformat if cursor is inside any of
" the following syntax groups
"
Expand All @@ -71,35 +71,54 @@ if !exists('g:pencil#autoformat_blacklist')
" mmdTable[A-Za-z0-9]* (mattly/vim-markdown-enhancements)
" txtCode (timcharper/textile.vim)
" rst*,tex*,asciidoc* (syntax file shipped with vim)
let g:pencil#autoformat_blacklist = [
\ 'markdown(Code|H[0-9]|Url|IdDeclaration|Link|Rule|Highlight[A-Za-z0-9]+)',
\ 'mkd(Code|Rule|Delimiter|Link|ListItem|IndentCode)',
\ 'htmlH[0-9]',
\ 'markdown(FencedCodeBlock|InlineCode)',
\ 'mmdTable[A-Za-z0-9]*',
\ 'txtCode',
\ 'rst(CodeBlock|Directive|LiteralBlock|Sections)',
\ 'tex(BeginEndName|Delimiter|DocType|InputFile|Math|RefZone|Title)',
\ 'texSection$',
\ 'asciidoc(AttributeList|ListLabel|Literal|SideBar|Source|Sect[0-9])',
\ 'asciidoc[A-Za-z]*(Block|Macro|Title)',
\ ]
let g:pencil#autoformat_config = {
\ 'markdown': {
\ 'black': [
\ 'markdown(Code|H[0-9]|Url|IdDeclaration|Link|Rule|Highlight[A-Za-z0-9]+)',
\ 'htmlH[0-9]',
\ 'markdown(FencedCodeBlock|InlineCode)',
\ 'mmdTable[A-Za-z0-9]*',
\ ],
\ 'white': [
\ 'markdown(Code|Link)',
\ ],
\ },
\ 'mkd': {
\ 'black': [
\ 'mkd(Code|Rule|Delimiter|Link|ListItem|IndentCode)',
\ 'htmlH[0-9]',
\ 'mmdTable[A-Za-z0-9]*',
\ ],
\ },
\ 'tex': {
\ 'black': [
\ 'tex(BeginEndName|Delimiter|DocType|InputFile|Math|RefZone|Title)',
\ 'texSection$',
\ ],
\ 'enforce-previous-line': 1,
\ },
\ 'asciidoc': {
\ 'black': [
\ 'asciidoc(AttributeList|AttributeEntry|ListLabel|Literal|SideBar|Source|Sect[0-9])',
\ 'asciidoc[A-Za-z]*(Block|Macro|Title)',
\ ],
\ 'white': [
\ 'asciidoc(AttributeRef|Macro)',
\ ],
\ 'enforce-previous-line': 1,
\ },
\ 'rst': {
\ 'black': [
\ 'rst(CodeBlock|Directive|LiteralBlock|Sections)',
\ ],
\ },
\ 'textile': {
\ 'black': [
\ 'txtCode',
\ ],
\ },
\ }
en
let g:pencil#autoformat_blacklist_re =
\ '\v(' . join(g:pencil#autoformat_blacklist, '|') . ')'

if !exists('g:pencil#autoformat_inline_whitelist')
" grant autoformat a reprieve (allow enabling) if any of
" following syntax groups doesn't dominate the whole line
"
"'markdownCode' (tpope/vim-markdown)
let g:pencil#autoformat_inline_whitelist = [
\ 'markdown(Code|Link)',
\ 'asciidoc(AttributeRef|Macro)',
\ ]
en
let g:pencil#autoformat_inline_whitelist_re =
\ '\v(' . join(g:pencil#autoformat_inline_whitelist, '|') . ')'

if !exists('g:pencil#joinspaces')
" by default, only one space after full stop (.)
Expand Down

0 comments on commit f89a3ac

Please sign in to comment.