From e661e83bea0a90fad8d991b2ddc5dfe3f38ecf65 Mon Sep 17 00:00:00 2001 From: Reed Esau Date: Wed, 5 Nov 2014 05:05:23 -0700 Subject: [PATCH] Fixes for #19 and #22 #19 Reorganized commands, making them prefix-oriented. (e.g., old: HardPencil, new: PencilHard). Legacy commands still enabled by default. #22 Better support of inline syntax for PencilHard mode --- README.markdown | 80 ++++++++++++++++++++++++++------------------- autoload/pencil.vim | 49 +++++++++++++++++++++++---- plugin/pencil.vim | 62 +++++++++++++++++++++++++---------- 3 files changed, 134 insertions(+), 57 deletions(-) diff --git a/README.markdown b/README.markdown index 738d43e..b3fbccc 100644 --- a/README.markdown +++ b/README.markdown @@ -8,32 +8,34 @@ ![demo](http://i.imgur.com/0KYl5vU.gif) - - - +[Note: demo will be updated soon with the _newly_ renamed commands (see +below), but the legacy ones still work.] + # Features The _pencil_ plugin aspires to make Vim as powerful a tool for writers as it is for coders by focusing narrowly on the handful of tweaks needed to smooth the path to writing prose. -* For editing prose-oriented file types such as _text_, _markdown_, - _mail_, _rst_, _tex_, and _textile_. +* For editing prose-oriented file types such as _text_, _markdown_, _mail_, + _rst_, _tex_, and _textile_. * Agnostic on soft line wrap _versus_ hard line breaks, supporting both * Auto-detects wrap mode via modeline and sampling * Adjusts navigation key mappings to suit the wrap mode -* Creates undo points on common punctuation during insert, including +* Creates undo points on common punctuation during Insert mode, including deletion via line `` and word `` -* When using hard line breaks, enables autoformat while inserting text... -* ...except for tables and code blocks where you won’t want it -* 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 (e.g., `_` and `*` markup for styled text in \_*Markdown*\_) -* Support for display of mode indicator (`␍` and `⤸`, e.g.) in the status - line +* When using hard line breaks, enables autoformat while inserting text, except + for tables and code blocks where you won’t want it +* 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 + (e.g., `_` and `*` markup for styled text in \_*Markdown*\_) +* Support for display of mode indicator (`␍` and `⤸`, e.g.) in the status line * Pure Vimscript with no dependencies -Need spell-check and other features? Vim is about customization. To -complete your editing environment, learn to configure Vim and draw upon -its rich ecosystem of plugins. +Need spell-check, distraction-free editing, and other features? Vim is about +customization. To complete your editing environment, learn to configure Vim and +draw upon its rich ecosystem of plugins. # Why use Vim for writing? @@ -143,21 +145,26 @@ if auto-detect might suggest soft line wrap. ## Commands +You can enable, disable, and toggle _pencil_ as a command: + +* `Pencil` - enable pencil with auto-detection +* `PencilOff` - removes navigation mappings and restores buffer to global settings +* `PencilToggle` - if on, turns off; if off, enables with detection + Because auto-detect might not work as intended, you can invoke a command to set the behavior for the current buffer: -* `SoftPencil` - enable soft line wrap mode -* `HardPencil` - enable hard line break mode -* `NoPencil` - removes navigation mappings and restores buffer to global settings -* `TogglePencil` - if on, turns off; if off, enables with detection +* `PencilSoft` - enable soft line wrap mode +* `PencilHard` - enable hard line break mode ## Automatic formatting -_The ‘autoformat’ feature affects *HardPencil* (hard line break) mode +_The ‘autoformat’ feature affects *PencilHard* (hard line break) mode only._ -When inserting text while in *HardPencil* mode, Vim’s autoformat feature will be -enabled by default and can offer many of the same benefits as soft line wrap. +When inserting text while in *PencilHard* mode, Vim’s autoformat feature +will be enabled by default and can offer many of the same benefits as +soft line wrap. A useful exception: if used with popular syntax modules\*, _pencil_ will **disable** autoformat when you enter Insert mode from inside a code block @@ -165,15 +172,15 @@ or table. (See the advanced section below for more details.) Where you need to manually enable/disable autoformat, you can do so with a command: -* `AutoPencil` - enables autoformat -* `ManualPencil` - disables autoformat -* `ShiftPencil` - toggle to enable if disabled, etc. +* `PFormat` - enables autoformat +* `PFormatOff` - disables autoformat +* `PFormatToggle` - toggle to enable if disabled, etc. Or optionally map the toggle command to a key of your choice in your `.vimrc`: ```vim -nnoremap p :ShiftPencil +nnoremap p :PFormatToggle ``` To set the default behavior, add to your `.vimrc`: @@ -214,9 +221,9 @@ nnoremap Q gwip ## Default textwidth -You can configure the textwidth to be used in **HardPencil** mode when no -textwidth is set globally, locally, or available via modeline. It defaults -to `74`, but you can change that value in your `.vimrc`: +You can configure the textwidth to be used in **PencilHard** mode when no +textwidth is set globally, locally, or available via modeline. It +defaults to `74`, but you can change that value in your `.vimrc`: ```vim let g:pencil#textwidth = 74 @@ -291,7 +298,7 @@ terminal to support **bold** and _italic_ styles. ## Status line indicator Your status line can reflect the wrap mode for _pencil_ buffers. For -example, `␍` to represent `HardPencil` (hard line break) mode. To +example, `␍` to represent `PencilHard` (hard line break) mode. To configure your status line and ruler, add to your `.vimrc`: ```vim @@ -351,13 +358,13 @@ statements into a function. ### Autoformat blacklisting -_The ‘autoformat’ feature affects *HardPencil* (hard line break) mode +_The ‘autoformat’ feature affects *PencilHard* (hard line break) mode only._ When editing formatted text, such as a table or code block, autoformat will wreak havoc with the formatting. In these cases you will want to -temporarily deactivate autoformat, such as with the `ManualPencil` or -`ShiftPencil` commands described above. However, in most cases, you won’t +temporarily deactivate autoformat, such as with the `PFormatOff` or +`PFormatToggle` commands described above. However, in most cases, you won’t need to do this. _pencil_ will detect the syntax highlight group at the cursor position to @@ -370,9 +377,11 @@ _not_ in the blacklist. The current blacklist is: ```vim let g:pencil#autoformat_blacklist = [ \ 'markdownCode', + \ 'markdownH[0-9]', \ 'markdownUrl', \ 'markdownIdDeclaration', - \ 'markdownLinkDelimiter', + \ 'markdownLink', + \ 'markdownRule', \ 'markdownHighlight[A-Za-z0-9]+', \ 'mkdCode', \ 'mkdIndentCode', @@ -473,10 +482,12 @@ Other plugins of specific interest to writers: * [tpope/vim-abolish][ab] - search for, substitute, and abbr. multiple variants of a word * [tommcdo/vim-exchange][ex] - easy text exchange operator for Vim * [junegunn/limelight.vim][jl] - focus mode that brightens current paragraph +* [junegunn/goyo.vim][jg] - distraction-free editing mode [ab]: http://github.com/tpope/vim-abolish [ex]: http://github.com/tommcdo/vim-exchange [jl]: http://github.com/junegunn/limelight.vim +[jg]: http://github.com/junegunn/goyo.vim [tvm]: http://github.com/tpope/vim-markdown [pvm]: http://github.com/plasticboy/vim-markdown [mvme]: http://github.com/mattly/vim-markdown-enhancements @@ -493,7 +504,8 @@ If you find the _pencil_ plugin useful, check out these others by [@reedes][re]: * [vim-wheel][wh] - screen-anchored cursor movement for Vim * [vim-wordy][wo] - uncovering usage problems in writing -Unimpressed by _pencil_? [vim-pandoc][vp] offers prose-oriented features with its own Markdown variant +Unimpressed by _pencil_? [vim-pandoc][vp] offers prose-oriented features +with its own Markdown variant. [cp]: http://github.com/reedes/vim-colors-pencil [lc]: http://github.com/reedes/vim-litecorrect diff --git a/autoload/pencil.vim b/autoload/pencil.vim index 3e379d5..532a9b7 100644 --- a/autoload/pencil.vim +++ b/autoload/pencil.vim @@ -5,7 +5,6 @@ " Created: December 28, 2013 " License: The MIT License (MIT) " ============================================================================ - if exists("autoloaded_pencil") | fini | en let autoloaded_pencil = 1 @@ -58,28 +57,37 @@ fun! s:maybe_enable_autoformat() let l:okay_to_enable = 1 let l:line = line('.') let l:col = col('.') + let l:last_col = col('$') let l:stack = [] + let l:found_empty = 0 " at end of line there may be no synstack, so scan back while l:col > 0 let l:stack = synstack(l:line, l:col) if l:stack != [] break en + " the last column will always be empty, so ignore it + if l:col < l:last_col + let l:found_empty = 1 + en let l:col -= 1 endw " if needed, scan towards end of line looking for highlight groups if l:stack == [] let l:col = col('.') + 1 - let l:last_col = col('$') while l:col <= l:last_col let l:stack = synstack(l:line, l:col) if l:stack != [] break en + " the last column will always be empty, so ignore it + if l:col < l:last_col + let l:found_empty = 1 + en let l:col += 1 endw en - " scan for matches to blacklist + " 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 @@ -87,24 +95,53 @@ fun! s:maybe_enable_autoformat() 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 + " one final check for an empty stack at the start of the line + if !l:found_empty + if synstack(l:line, 1) == [] + let l:found_empty = 1 + en + en + if l:found_empty + for l:sid in l:stack + if match(synIDattr(l:sid, 'name'), + \ g:pencil#autoformat_inline_whitelist_re) >= 0 + let l:okay_to_enable = 1 + en + endfo + en + en if l:okay_to_enable set formatoptions+=a en endf -fun! pencil#setAutoFormat(mode) +fun! pencil#setAutoFormat(af) " 1=auto, 0=manual, -1=toggle if !exists('b:last_autoformat') let b:last_autoformat = 0 en - let b:last_autoformat = a:mode ==# -1 ? !b:last_autoformat : a:mode - if b:last_autoformat + let l:nu_af = a:af ==# -1 ? !b:last_autoformat : a:af + let l:is_hard = + \ exists('b:pencil_wrap_mode') && + \ b:pencil_wrap_mode ==# s:WRAP_MODE_HARD + if l:nu_af && l:is_hard aug pencil_autoformat au InsertEnter call s:maybe_enable_autoformat() au InsertLeave set formatoptions-=a aug END + let b:last_autoformat = l:nu_af el sil! au! pencil_autoformat * + if l:nu_af && !l:is_hard + echohl WarningMsg + echo "autoformat can only be enabled in hard break line mode" + echohl NONE + return + en en endf diff --git a/plugin/pencil.vim b/plugin/pencil.vim index 9927bca..aea7db4 100644 --- a/plugin/pencil.vim +++ b/plugin/pencil.vim @@ -29,11 +29,11 @@ endf fun! PencilMode() if exists('b:pencil_wrap_mode') if b:pencil_wrap_mode ==# s:WRAP_MODE_SOFT - return get(g:pencil#mode_indicators, 'soft', 'soft') + return get(g:pencil#mode_indicators, 'soft', 'S') elsei b:pencil_wrap_mode ==# s:WRAP_MODE_HARD - return get(g:pencil#mode_indicators, 'hard', 'hard') + return get(g:pencil#mode_indicators, 'hard', 'H') el - return get(g:pencil#mode_indicators, 'off', 'off') + return get(g:pencil#mode_indicators, 'off', '') en else return '' " should be blank for non-prose modes @@ -61,8 +61,7 @@ if !exists('g:pencil#autoformat_blacklist') " by default, pencil does NOT start autoformat if inside any of " the following syntax groups " - "'markdownCode', 'markdownUrl', 'markdownIdDeclaration', - "'markdownLinkDelimiter', 'markdownHighlight[A-Za-z0-9]+' (tpope/vim-markdown) + "'markdown*' (tpope/vim-markdown) "'mkdCode', 'mkdIndentCode' (plasticboy/vim-markdown) "'markdownFencedCodeBlock', 'markdownInlineCode' (gabrielelana/vim-markdown) "'mmdTable[A-Za-z0-9]*' (mattly/vim-markdown-enhancements) @@ -71,9 +70,11 @@ if !exists('g:pencil#autoformat_blacklist') "'tex*' (syntax file shipped with vim) let g:pencil#autoformat_blacklist = [ \ 'markdownCode', + \ 'markdownH[0-9]', \ 'markdownUrl', \ 'markdownIdDeclaration', - \ 'markdownLinkDelimiter', + \ 'markdownLink', + \ 'markdownRule', \ 'markdownHighlight[A-Za-z0-9]+', \ 'mkdCode', \ 'mkdIndentCode', @@ -98,6 +99,19 @@ 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 = [ + \ 'markdownCode', + \ 'markdownLink', + \ ] +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 (.) let g:pencil#joinspaces = 0 @@ -137,22 +151,36 @@ if !exists('g:pencil#mode_indicators') " used to set PencilMode() for statusline if s:unicode_enabled() let g:pencil#mode_indicators = {'hard': '␍', 'soft': '⤸', 'off': '',} - "let g:pencil#mode_indicators = {'hard': '✐ hard', 'soft': '✎ soft', 'off': '✎ off',} el - let g:pencil#mode_indicators = {'hard': 'hard', 'soft': 'soft', 'off': '',} + let g:pencil#mode_indicators = {'hard': 'H', 'soft': 'S', 'off': '',} en en -" # coms -com -nargs=0 HardPencil call pencil#init({'wrap': 'hard'}) -com -nargs=0 SoftPencil call pencil#init({'wrap': 'soft'}) -com -nargs=0 DropPencil call pencil#init({'wrap': 'off' }) -com -nargs=0 NoPencil call pencil#init({'wrap': 'off' }) -com -nargs=0 TogglePencil call pencil#init({'wrap': 'toggle'}) +" Commands -com -nargs=0 AutoPencil call pencil#setAutoFormat(1) -com -nargs=0 ManualPencil call pencil#setAutoFormat(0) -com -nargs=0 ShiftPencil call pencil#setAutoFormat(-1) +com -nargs=0 Pencil call pencil#init({'wrap': 'on' }) +com -nargs=0 PencilOff call pencil#init({'wrap': 'off' }) +com -nargs=0 PencilHard call pencil#init({'wrap': 'hard'}) +com -nargs=0 PencilSoft call pencil#init({'wrap': 'soft'}) +com -nargs=0 PencilToggle call pencil#init({'wrap': 'toggle'}) +com -nargs=0 PFormat call pencil#setAutoFormat(1) +com -nargs=0 PFormatOff call pencil#setAutoFormat(0) +com -nargs=0 PFormatToggle call pencil#setAutoFormat(-1) + +" NOTE: legacy commands will be disabled by default at some point +if !exists('g:pencil#legacyCommands') + let g:pencil#legacyCommands = 1 +en +if g:pencil#legacyCommands + com -nargs=0 HardPencil call pencil#init({'wrap': 'hard'}) + com -nargs=0 SoftPencil call pencil#init({'wrap': 'soft'}) + com -nargs=0 DropPencil call pencil#init({'wrap': 'off' }) + com -nargs=0 NoPencil call pencil#init({'wrap': 'off' }) + com -nargs=0 TogglePencil call pencil#init({'wrap': 'toggle'}) + com -nargs=0 AutoPencil call pencil#setAutoFormat(1) + com -nargs=0 ManualPencil call pencil#setAutoFormat(0) + com -nargs=0 ShiftPencil call pencil#setAutoFormat(-1) +en let &cpo = s:save_cpo unlet s:save_cpo