-
Notifications
You must be signed in to change notification settings - Fork 2
/
TextTransform.vim
198 lines (183 loc) · 7.93 KB
/
TextTransform.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
" TextTransform.vim: Create text transformation mappings and commands.
"
" DEPENDENCIES:
" - TextTransform#Arbitrary.vim autoload script
" - TextTransform#Lines.vim autoload script
" - ingo/err.vim autoload script
"
" Copyright: (C) 2011-2014 Ingo Karkat
" The VIM LICENSE applies to this script; see ':help copyright'.
" Idea, design and implementation based on unimpaired.vim (vimscript #1590)
" by Tim Pope.
"
" Maintainer: Ingo Karkat <ingo@karkat.de>
"
" REVISION DATE REMARKS
" 1.24.016 13-Jun-2014 ENH: Allow optional [!] for made commands, and
" suppress the "Nothing transformed" error in that
" case. This can help when using the resulting
" command as an optional step, as prefixing with
" :silent! can be difficult to combine with
" ranges, and would suppress _all_ transformation
" errors.
" 1.20.015 25-Sep-2013 Allow to pass command arguments, which are then
" accessible to the algorithm through
" g:TextTransformContext.arguments.
" 1.20.014 16-Sep-2013 Provide separate <Plug>TextR... repeat mappings
" to be able to distinguish between a mapping and
" its repeat via repeat.vim.
" 1.12.013 26-Jun-2013 Also perform the no-op check for the generated
" commands. This avoids the attempted processing
" and gives a better error message than the
" current "E21: Cannot make changes, 'modifiable'
" is off: 10,10delete _"
" Abort commands in case of error.
" 1.12.012 14-Jun-2013 Minor: Make substitute() robust against
" 'ignorecase'.
" 1.04.011 28-Dec-2012 Minor: Correct lnum for no-modifiable buffer
" check.
" 1.00.010 05-Apr-2012 Initial release.
" 010 19-Oct-2011 BUG: Variable rename from LineTypes to
" l:selectionModes broke Funcref arguments; my
" test suite would have caught this, if only I had
" run it :-)
" 009 11-Apr-2011 Implement customization of mappings (by having
" mappings to the <Plug>-mappings) and no custom
" mappings (by passing an empty a:key), just the
" <Plug>-mappings.
" 008 10-Apr-2011 Define commands with bang; otherwise,
" buffer-local commands defined by ftplugins will
" cause errors when the filetype changes (to one
" that defines the same commands).
" 007 05-Apr-2011 Add TextTransform#MakeSelectionCommand() command
" variant that uses s:Transform() and allows to
" operate on text objects, motions, visual
" selection, ...
" Replace "unimpaired" prefix with "TextT" to
" remove the last remnant of the original
" unimpaired.vim script and make this fully
" independent.
" 006 05-Apr-2011 Limit the amount of script that gets sourced
" when commands / mappings are defined during Vim
" startup:
" Extract actual transformations on lines to
" TextTransform#Lines.vim.
" Extract actual transformations in mappings to
" TextTransform#Arbitrary.vim.
" 005 29-Mar-2011 Rename TextTransform#MapTransform() to
" TextTransform#MakeMappings().
" Implement 'isProcessEntireText' option.
" Factor out s:TransformCommand() function and
" make it delegate to the passed
" a:ProcessFunction, which is either
" s:TransformLinewise() or s:TransformWholeText().
" 004 28-Mar-2011 ENH: Allow use of Funcref for a:algorithm in
" order to support script-local transformation
" functions.
" 003 25-Mar-2011 ENH: Use s:TransformExpression() instead of
" s:TransformSetup() to enable passing <count>
" before the operator-pending mapping.
" Tighten pattern to detect visualmode() arguments
" in s:Transform().
" Implement TextTransform#MakeCommand() for
" linewise application of the algorithm.
" ENH: Catch and report errors in algorithm.
" ENH: Do not make the buffer modified if no
" transformation is done.
" 002 16-Mar-2011 Fix off-by-one errors with some modes and
" 'selection' settings.
" FIX: Parsing for l:doubledKey now also accepts
" key modifiers like "<S-...>".
" 001 07-Mar-2011 file creation from plugin/unimpaired.vim
function! s:Before()
let s:isModified = &l:modified
endfunction
function! s:After()
if ! s:isModified
setlocal nomodified
endif
unlet s:isModified
endfunction
nnoremap <expr> <SID>Reselect '1v' . (visualmode() !=# 'V' && &selection ==# 'exclusive' ? ' ' : '')
function! TextTransform#MakeMappings( mapArgs, key, algorithm, ... )
" This will cause "E474: Invalid argument" if the mapping name gets too long.
let l:algorithmMappingName = (
\ type(a:algorithm) == type('') ?
\ a:algorithm :
\ substitute(substitute(string(a:algorithm), '^\Cfunction(''\(.*\)'')', '\1', ''), '\C<SNR>', '', 'g')
\)
let l:mappingName = 'TextT' . l:algorithmMappingName
let l:repeatMappingName = 'TextR' . l:algorithmMappingName
let l:plugMappingName = '<Plug>' . l:mappingName
execute printf('nnoremap <silent> <expr> %s %sOperator TextTransform#Arbitrary#Expression(%s, %s)',
\ a:mapArgs,
\ l:plugMappingName,
\ string(a:algorithm),
\ string(l:repeatMappingName)
\)
" Repeat not defined in visual mode.
let l:noopModificationCheck = 'call <SID>Before()<Bar>call setline(".", getline("."))<Bar>call <SID>After()<Bar>'
for [l:mappingName, l:isRepeat] in [[l:mappingName, 0], [l:repeatMappingName, 1]]
execute printf('vnoremap <silent> %s <SID>%sVisual :<C-u>%scall TextTransform#Arbitrary#Visual(%s, %s, %d)<CR>',
\ a:mapArgs,
\ l:mappingName,
\ l:noopModificationCheck,
\ string(a:algorithm),
\ string(l:repeatMappingName),
\ l:isRepeat
\)
execute printf('vnoremap <silent> <script> <Plug>%sVisual <SID>%sVisual',
\ l:mappingName,
\ l:mappingName
\)
execute printf('nnoremap <silent> <script> <Plug>%sVisual <SID>Reselect<SID>%sVisual',
\ l:mappingName,
\ l:mappingName
\)
let l:SelectionModes = (a:0 ? a:1 : 'lines')
execute printf('nnoremap <silent> %s <Plug>%sLine :<C-u>%scall TextTransform#Arbitrary#Line(%s, %s, %s, %d)<CR>',
\ a:mapArgs,
\ l:mappingName,
\ l:noopModificationCheck,
\ string(a:algorithm),
\ string(l:SelectionModes),
\ string(l:repeatMappingName),
\ l:isRepeat
\)
endfor
if empty(a:key)
return
endif
let l:operatorPlugMappingName = l:plugMappingName . 'Operator'
if ! hasmapto(l:operatorPlugMappingName, 'n')
execute 'nmap' a:mapArgs a:key l:operatorPlugMappingName
endif
let l:visualPlugMappingName = l:plugMappingName . 'Visual'
if ! hasmapto(l:visualPlugMappingName, 'x')
execute 'xmap' a:mapArgs a:key l:visualPlugMappingName
endif
let l:linePlugMappingName = l:plugMappingName . 'Line'
if ! hasmapto(l:linePlugMappingName, 'n')
let l:doubledKey = matchstr(a:key, '\(<[[:alpha:]-]\+>\|.\)$')
execute 'nmap' a:mapArgs a:key . l:doubledKey l:linePlugMappingName
endif
endfunction
function! TextTransform#MakeCommand( commandOptions, commandName, algorithm, ... )
let l:options = (a:0 ? a:1 : {})
execute printf('command! -bar -bang %s %s %s call <SID>Before() | call setline(<line1>, getline(<line1>)) | call <SID>After() | if ! TextTransform#Lines#TransformCommand(<line1>, <line2>, <bang>0, %s, %s, <f-args>) | if <bang>1 || ingo#err#Get() !=# "Nothing transformed" | echoerr ingo#err#Get() | endif | endif',
\ a:commandOptions,
\ (a:commandOptions =~# '\%(^\|\s\)-range\%(=\|\s\)' ? '' : '-range'),
\ a:commandName,
\ string(a:algorithm),
\ string('TextTransform#Lines#Transform' . (get(l:options, 'isProcessEntireText', 0) ? 'WholeText' : 'Linewise'))
\)
endfunction
function! TextTransform#MakeSelectionCommand( commandOptions, commandName, algorithm, selectionModes )
execute printf('command -bar -bang -count %s %s call <SID>Before() | call setline(<line1>, getline(<line1>)) | call <SID>After() | if ! TextTransform#Arbitrary#Command(<line1>, <line2>, <bang>0, <count>, %s, %s, <f-args>) | if <bang>1 || ingo#err#Get() !=# "Nothing transformed" | echoerr ingo#err#Get() | endif | endif',
\ a:commandOptions,
\ a:commandName,
\ string(a:algorithm),
\ string(a:selectionModes)
\)
endfunction
" vim: set ts=8 sts=4 sw=4 noexpandtab ff=unix fdm=syntax :