|
1 | | -" Function to left and right align text. |
2 | | -" |
3 | | -" Written by: Preben "Peppe" Guldberg <[email protected]> |
4 | | -" Created: 980806 14:13 (or around that time anyway) |
5 | | -" Revised: 001103 00:36 (See "Revisions" below) |
6 | | - |
7 | | - |
8 | | -" function Justify( [ textwidth [, maxspaces [, indent] ] ] ) |
9 | | -" |
10 | | -" Justify() will left and right align a line by filling in an |
11 | | -" appropriate amount of spaces. Extra spaces are added to existing |
12 | | -" spaces starting from the right side of the line. As an example, the |
13 | | -" following documentation has been justified. |
14 | | -" |
15 | | -" The function takes the following arguments: |
16 | | - |
17 | | -" textwidth argument |
18 | | -" ------------------ |
19 | | -" If not specified, the value of the 'textwidth' option is used. If |
20 | | -" 'textwidth' is zero a value of 80 is used. |
21 | | -" |
22 | | -" Additionally the arguments 'tw' and '' are accepted. The value of |
23 | | -" 'textwidth' will be used. These are handy, if you just want to specify |
24 | | -" the maxspaces argument. |
25 | | - |
26 | | -" maxspaces argument |
27 | | -" ------------------ |
28 | | -" If specified, alignment will only be done, if the longest space run |
29 | | -" after alignment is no longer than maxspaces. |
30 | | -" |
31 | | -" An argument of '' is accepted, should the user like to specify all |
32 | | -" arguments. |
33 | | -" |
34 | | -" To aid user defined commands, negative values are accepted aswell. |
35 | | -" Using a negative value specifies the default behaviour: any length of |
36 | | -" space runs will be used to justify the text. |
37 | | - |
38 | | -" indent argument |
39 | | -" --------------- |
40 | | -" This argument specifies how a line should be indented. The default is |
41 | | -" to keep the current indentation. |
42 | | -" |
43 | | -" Negative values: Keep current amount of leading whitespace. |
44 | | -" Positive values: Indent all lines with leading whitespace using this |
45 | | -" amount of whitespace. |
46 | | -" |
47 | | -" Note that the value 0, needs to be quoted as a string. This value |
48 | | -" leads to a left flushed text. |
49 | | -" |
50 | | -" Additionally units of 'shiftwidth'/'sw' and 'tabstop'/'ts' may be |
51 | | -" added. In this case, if the value of indent is positive, the amount of |
52 | | -" whitespace to be added will be multiplied by the value of the |
53 | | -" 'shiftwidth' and 'tabstop' settings. If these units are used, the |
54 | | -" argument must be given as a string, eg. Justify('','','2sw'). |
55 | | -" |
56 | | -" If the values of 'sw' or 'tw' are negative, they are treated as if |
57 | | -" they were 0, which means that the text is flushed left. There is no |
58 | | -" check if a negative number prefix is used to change the sign of a |
59 | | -" negative 'sw' or 'ts' value. |
60 | | -" |
61 | | -" As with the other arguments, '' may be used to get the default |
62 | | -" behaviour. |
63 | | - |
64 | | - |
65 | | -" Notes: |
66 | | -" |
67 | | -" If the line, adjusted for space runs and leading/trailing whitespace, |
68 | | -" is wider than the used textwidth, the line will be left untouched (no |
69 | | -" whitespace removed). This should be equivalent to the behaviour of |
70 | | -" :left, :right and :center. |
71 | | -" |
72 | | -" If the resulting line is shorter than the used textwidth it is left |
73 | | -" untouched. |
74 | | -" |
75 | | -" All space runs in the line are truncated before the alignment is |
76 | | -" carried out. |
77 | | -" |
78 | | -" If you have set 'noexpandtab', :retab! is used to replace space runs |
79 | | -" with whitespace using the value of 'tabstop'. This should be |
80 | | -" conformant with :left, :right and :center. |
81 | | -" |
82 | | -" If joinspaces is set, an extra space is added after '.', '?' and '!'. |
83 | | -" If 'cpooptions' include 'j', extra space is only added after '.'. |
84 | | -" (This may on occasion conflict with maxspaces.) |
85 | | - |
86 | | - |
87 | | -" Related mappings: |
88 | | -" |
89 | | -" Mappings that will align text using the current text width, using at |
90 | | -" most four spaces in a space run and keeping current indentation. |
91 | | -nmap _j :%call Justify('tw',4)<CR> |
92 | | -vmap _j :call Justify('tw',4)<CR> |
93 | | -" |
94 | | -" Mappings that will remove space runs and format lines (might be useful |
95 | | -" prior to aligning the text). |
96 | | -nmap ,gq :%s/\s\+/ /g<CR>gq1G |
97 | | -vmap ,gq :s/\s\+/ /g<CR>gvgq |
98 | | -
|
99 | | - |
100 | | -" User defined command: |
101 | | -" |
102 | | -" The following is an ex command that works as a shortcut to the Justify |
103 | | -" function. Arguments to Justify() can be added after the command. |
104 | | -com! -range -nargs=* Justify <line1>,<line2>call Justify(<f-args>) |
105 | | -" |
106 | | -" The following commands are all equivalent: |
107 | | -" |
108 | | -" 1. Simplest use of Justify(): |
109 | | -" :call Justify() |
110 | | -" :Justify |
111 | | -" |
112 | | -" 2. The _j mapping above via the ex command: |
113 | | -" :%Justify tw 4 |
114 | | -" |
115 | | -" 3. Justify visualised text at 72nd column while indenting all |
116 | | -" previously indented text two shiftwidths |
117 | | -" :'<,'>call Justify(72,'','2sw') |
118 | | -" :'<,'>Justify 72 -1 2sw |
119 | | -" |
120 | | -" This documentation has been justified using the following command: |
121 | | -":se et|kz|1;/^" function Justify(/+,'z-g/^" /s/^" //|call Justify(70,3)|s/^/" / |
122 | | - |
123 | | -" Revisions: |
124 | | -" 001103: If 'joinspaces' was set, calculations could be wrong. |
125 | | -" Tabs at start of line could also lead to errors. |
126 | | -" Use setline() instead of "exec 's/foo/bar/' - safer. |
127 | | -" Cleaned up the code a bit. |
128 | | -" |
129 | | -" Todo: Convert maps to the new script specific form |
130 | | - |
131 | | -" Error function |
132 | | -function! Justify_error(message) |
133 | | - echohl Error |
134 | | - echo "Justify([tw, [maxspaces [, indent]]]): " . a:message |
135 | | - echohl None |
136 | | -endfunction |
137 | | - |
138 | | - |
139 | | -" Now for the real thing |
140 | | -function! Justify(...) range |
141 | | - |
142 | | - if a:0 > 3 |
143 | | - call Justify_error("Too many arguments (max 3)") |
144 | | - return 1 |
145 | | - endif |
146 | | - |
147 | | - " Set textwidth (accept 'tw' and '' as arguments) |
148 | | - if a:0 >= 1 |
149 | | - if a:1 =~ '^\(tw\)\=$' |
150 | | - let tw = &tw |
151 | | - elseif a:1 =~ '^\d\+$' |
152 | | - let tw = a:1 |
153 | | - else |
154 | | - call Justify_error("tw must be a number (>0), '' or 'tw'") |
155 | | - return 2 |
156 | | - endif |
157 | | - else |
158 | | - let tw = &tw |
159 | | - endif |
160 | | - if tw == 0 |
161 | | - let tw = 80 |
162 | | - endif |
163 | | - |
164 | | - " Set maximum number of spaces between WORDs |
165 | | - if a:0 >= 2 |
166 | | - if a:2 == '' |
167 | | - let maxspaces = tw |
168 | | - elseif a:2 =~ '^-\d\+$' |
169 | | - let maxspaces = tw |
170 | | - elseif a:2 =~ '^\d\+$' |
171 | | - let maxspaces = a:2 |
172 | | - else |
173 | | - call Justify_error("maxspaces must be a number or ''") |
174 | | - return 3 |
175 | | - endif |
176 | | - else |
177 | | - let maxspaces = tw |
178 | | - endif |
179 | | - if maxspaces <= 1 |
180 | | - call Justify_error("maxspaces should be larger than 1") |
181 | | - return 4 |
182 | | - endif |
183 | | - |
184 | | - " Set the indentation style (accept sw and ts units) |
185 | | - let indent_fix = '' |
186 | | - if a:0 >= 3 |
187 | | - if (a:3 == '') || a:3 =~ '^-[1-9]\d*\(shiftwidth\|sw\|tabstop\|ts\)\=$' |
188 | | - let indent = -1 |
189 | | - elseif a:3 =~ '^-\=0\(shiftwidth\|sw\|tabstop\|ts\)\=$' |
190 | | - let indent = 0 |
191 | | - elseif a:3 =~ '^\d\+\(shiftwidth\|sw\|tabstop\|ts\)\=$' |
192 | | - let indent = substitute(a:3, '\D', '', 'g') |
193 | | - elseif a:3 =~ '^\(shiftwidth\|sw\|tabstop\|ts\)$' |
194 | | - let indent = 1 |
195 | | - else |
196 | | - call Justify_error("indent: a number with 'sw'/'ts' unit") |
197 | | - return 5 |
198 | | - endif |
199 | | - if indent >= 0 |
200 | | - while indent > 0 |
201 | | - let indent_fix = indent_fix . ' ' |
202 | | - let indent = indent - 1 |
203 | | - endwhile |
204 | | - let indent_sw = 0 |
205 | | - if a:3 =~ '\(shiftwidth\|sw\)' |
206 | | - let indent_sw = &sw |
207 | | - elseif a:3 =~ '\(tabstop\|ts\)' |
208 | | - let indent_sw = &ts |
209 | | - endif |
210 | | - let indent_fix2 = '' |
211 | | - while indent_sw > 0 |
212 | | - let indent_fix2 = indent_fix2 . indent_fix |
213 | | - let indent_sw = indent_sw - 1 |
214 | | - endwhile |
215 | | - let indent_fix = indent_fix2 |
216 | | - endif |
217 | | - else |
218 | | - let indent = -1 |
219 | | - endif |
220 | | - |
221 | | - " Avoid substitution reports |
222 | | - let save_report = &report |
223 | | - set report=1000000 |
224 | | - |
225 | | - " Check 'joinspaces' and 'cpo' |
226 | | - if &js == 1 |
227 | | - if &cpo =~ 'j' |
228 | | - let join_str = '\(\. \)' |
229 | | - else |
230 | | - let join_str = '\([.!?!] \)' |
231 | | - endif |
232 | | - endif |
233 | | - |
234 | | - let cur = a:firstline |
235 | | - while cur <= a:lastline |
236 | | - |
237 | | - let str_orig = getline(cur) |
238 | | - let save_et = &et |
239 | | - set et |
240 | | - exec cur . "retab" |
241 | | - let &et = save_et |
242 | | - let str = getline(cur) |
243 | | - |
244 | | - let indent_str = indent_fix |
245 | | - let indent_n = strlen(indent_str) |
246 | | - " Shall we remember the current indentation |
247 | | - if indent < 0 |
248 | | - let indent_orig = matchstr(str_orig, '^\s*') |
249 | | - if strlen(indent_orig) > 0 |
250 | | - let indent_str = indent_orig |
251 | | - let indent_n = strlen(matchstr(str, '^\s*')) |
252 | | - endif |
253 | | - endif |
254 | | - |
255 | | - " Trim trailing, leading and running whitespace |
256 | | - let str = substitute(str, '\s\+$', '', '') |
257 | | - let str = substitute(str, '^\s\+', '', '') |
258 | | - let str = substitute(str, '\s\+', ' ', 'g') |
259 | | - let str_n = strdisplaywidth(str) |
260 | | - |
261 | | - " Possible addition of space after punctuation |
262 | | - if exists("join_str") |
263 | | - let str = substitute(str, join_str, '\1 ', 'g') |
264 | | - endif |
265 | | - let join_n = strdisplaywidth(str) - str_n |
266 | | - |
267 | | - " Can extraspaces be added? |
268 | | - " Note that str_n may be less than strlen(str) [joinspaces above] |
269 | | - if strdisplaywidth(str) <= tw - indent_n && str_n > 0 |
270 | | - " How many spaces should be added |
271 | | - let s_add = tw - str_n - indent_n - join_n |
272 | | - let s_nr = strlen(substitute(str, '\S', '', 'g') ) - join_n |
273 | | - let s_dup = s_add / s_nr |
274 | | - let s_mod = s_add % s_nr |
275 | | - |
276 | | - " Test if the changed line fits with tw |
277 | | - if 0 <= (str_n + (maxspaces - 1)*s_nr + indent_n) - tw |
278 | | - |
279 | | - " Duplicate spaces |
280 | | - while s_dup > 0 |
281 | | - let str = substitute(str, '\( \+\)', ' \1', 'g') |
282 | | - let s_dup = s_dup - 1 |
283 | | - endwhile |
284 | | - |
285 | | - " Add extra spaces from the end |
286 | | - while s_mod > 0 |
287 | | - let str = substitute(str, '\(\(\s\+\S\+\)\{' . s_mod . '}\)$', ' \1', '') |
288 | | - let s_mod = s_mod - 1 |
289 | | - endwhile |
290 | | - |
291 | | - " Indent the line |
292 | | - if indent_n > 0 |
293 | | - let str = substitute(str, '^', indent_str, '' ) |
294 | | - endif |
295 | | - |
296 | | - " Replace the line |
297 | | - call setline(cur, str) |
298 | | - |
299 | | - " Convert to whitespace |
300 | | - if &et == 0 |
301 | | - exec cur . 'retab!' |
302 | | - endif |
303 | | - |
304 | | - endif " Change of line |
305 | | - endif " Possible change |
306 | | - |
307 | | - let cur = cur + 1 |
308 | | - endwhile |
309 | | - |
310 | | - norm ^ |
311 | | - |
312 | | - let &report = save_report |
313 | | - |
314 | | -endfunction |
315 | | - |
316 | | -" EOF vim: tw=78 ts=8 sw=4 sts=4 noet ai |
| 1 | +" Load the justify package. |
| 2 | +" For those users who were loading the justify plugin from here. |
| 3 | +packadd justify |
0 commit comments