@@ -6,82 +6,133 @@ if exists("load_pangu_space")
66endif
77let load_pangu_space= 1
88
9- let g: pangu_enabled= 1
10-
11- function ! PanGuSpacingCore ()
12- let ignore = search (" PANGU_DISABLE" , ' n' )
13- if (ignore > 0 )
14- return
15- endif
16-
17- if &ft != " diff"
18- let l: save_regexpengine = ®expengine
19- let ®expengine = 2
20-
21- let b: curcol = col (" ." )
22- let b: curline = line (" ." )
23-
24- " 汉字后的标点符号,转成全角符号。
25- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\)\.\($\|\s\+\)/ \1 。/g
26- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\),\s*/ \1 ,/g
27- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\);\s*/ \1 ;/g
28- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\)!\s*/ \1 !/g
29- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\):\s*/ \1 :/g
30- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\)?\s*/ \1 ?/g
31- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\)\\\s*/ \1 、/g
32- silent ! % s /(\([\u4e00-\u9fa5\u3040-\u30FF]\)/ (\1 /g
33- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\))/ \1 )/g
34- silent ! % s /\[\([\u4e00-\u9fa5\u3040-\u30FF]\)/ 『\1 /g
35- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\)\]/ \1 』/g
36- silent ! % s /<\([\u4e00-\u9fa5\u3040-\u30FF]\)/ 《\1 /g
37- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\)>/ \1 》/g
38- " TODO: 半角单双引号无法有效判断起始和结束,以正确替换成全角单双引号。
39- " 可以考虑通过标识符号提醒。
40-
41- " 连续的句号转成省略号
42- " - `……`
43- " - `⋯⋯`
44- " - `......`
45- " - `······`
46- " @see [中文省略号应该垂直居中还是沉底?](https://www.zhihu.com/question/19593470)
47- silent ! % s /。\{3,}/ ...... /g
48-
49- " #11: 根据《标点符号用法》,重复的感叹号、问号不允许超过 3 个。
50- " [标点符号用法 GB/T 15834 2011](http://www.moe.gov.cn/ewebeditor/uploadfile/2015/01/13/20150113091548267.pdf)
51- silent ! % s /\([!?]\)\1\{3,}/ \1\1\1 /g
52- silent ! % s /\([。,;:、“”『』〖〗《》]\)\1\{1,}/ \1 /g
53-
54- " 全角数字、英文字符、英文标点。
55- " 65248 是相对应的全角和半角的 Unicode 偏差。
56- silent ! % s /\([0-9A-Za-z@]\)/ \= nr2char (char2nr (submatch (0 ))-65248 )/g
57-
58- " 汉字与其前后的英文字符、英文标点、数字间增加空白。
59- silent ! % s /\([\u4e00-\u9fa5\u3040-\u30FF]\)\([a-zA-Z0-9@&=\[\$\%\^\-\+(\/\\]\)/ \1 \2 /g " 汉字在前。
60- silent ! % s /\([a-zA-Z0-9!&;=\]\,\.\:\?\$\%\^\-\+\)\/\\]\)\([\u4e00-\u9fa5\u3040-\u30FF]\)/ \1 \2 /g " 汉字在后。
61-
62- " 修复 markdown 链接所使用的标点。
63- silent ! % s /[『[]\([^』\]]\+\)[』\]][『[]\([^』\]]\+\)[』\]]/ [\1 ][\2 ]/g " 参考链接
64- silent ! % s /[『[]\([^』\]]\+\)[』\]][((]\([^』)]\+\)[))]/ [\1 ](\2 )/g " 内联链接
65- " WiKi 链接:
66- " - [『中文条目』] -> [[中文条目]]
67- " - [[en 条目』] -> [[en 条目]]
68- " - [『条目 en]] -> [[条目 en]]
69- silent ! % s /\[[『[]\([^』\]]\+\)[』\]]\]/ [[\1 ]]/g
70-
71- silent ! % s /^ \[/ [/
72- silent ! % s /\s\+$/ /
73-
74- call cursor (b: curline , b: curcol )
75- let ®expengine = l: save_regexpengine
76- endif
9+ if ! exists (" g:pangu_enabled" )
10+ let g: pangu_enabled= 1
11+ endif
12+
13+ if ! exists (" g:pangu_rule_fullwidth_punctuation" )
14+ let g: pangu_rule_fullwidth_punctuation= 1
15+ endif
16+ if ! exists (" g:pangu_rule_duplicate_punctuation" )
17+ let g: pangu_rule_duplicate_punctuation= 1
18+ endif
19+ if ! exists (" g:pangu_rule_fullwidth_alphabet" )
20+ let g: pangu_rule_fullwidth_alphabet= 1
21+ endif
22+ if ! exists (" g:pangu_rule_spacing" )
23+ let g: pangu_rule_spacing= 1
24+ endif
25+ if ! exists (" g:pangu_rule_trailing_whitespace" )
26+ let g: pangu_rule_trailing_whitespace= 1
27+ endif
28+
29+ function ! PanGuSpacingCore (mode ) range
30+ let ignore = search (" PANGU_DISABLE" , ' n' )
31+ if (ignore > 0 )
32+ return
33+ endif
34+
35+ if &ft == " diff"
36+ return
37+ endif
38+
39+ let savedpos = getpos (" v" )
40+
41+ let l: save_regexpengine = ®expengine
42+ let ®expengine = 2
43+
44+ let firstline = a: firstline
45+ let lastline = a: lastline
46+ " 规范化模式:
47+ " - ALL: 全局规范化
48+ " - RANGE: 区域规范化
49+ if a: mode == " ALL"
50+ let firstline = 1
51+ let lastline = line (" $" )
52+ endif
53+
54+ " 汉字后的标点符号,转成全角符号。
55+ if g: pangu_rule_fullwidth_punctuation == 1
56+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\)\.\($\|\s\+\)/\1。/g'
57+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\),\s*/\1,/g'
58+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\);\s*/\1;/g'
59+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\)!\s*/\1!/g'
60+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\):\s*/\1:/g'
61+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\)?\s*/\1?/g'
62+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\)\\\s*/\1、/g'
63+ silent ! execute firstline . ' ,' . lastline . ' s/(\([\u4e00-\u9fa5\u3040-\u30FF]\)/(\1/g'
64+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\))/\1)/g'
65+ silent ! execute firstline . ' ,' . lastline . ' s/\[\([\u4e00-\u9fa5\u3040-\u30FF]\)/『\1/g'
66+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\)\]/\1』/g'
67+ silent ! execute firstline . ' ,' . lastline . ' s/<\([\u4e00-\u9fa5\u3040-\u30FF]\)/《\1/g'
68+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\)>/\1》/g'
69+
70+ " 修复 markdown 链接所使用的标点。
71+ " 参考链接
72+ silent ! execute firstline . ' ,' . lastline . ' s/[『[]\([^』\]]\+\)[』\]][『[]\([^』\]]\+\)[』\]]/[\1][\2]/g'
73+ " 内联链接
74+ silent ! execute firstline . ' ,' . lastline . ' s/[『[]\([^』\]]\+\)[』\]][((]\([^』)]\+\)[))]/[\1](\2)/g'
75+ " WiKi 链接:
76+ " - [『中文条目』] -> [[中文条目]]
77+ " - [[en 条目』] -> [[en 条目]]
78+ " - [『条目 en]] -> [[条目 en]]
79+ silent ! execute firstline . ' ,' . lastline . ' s/\[[『[]\([^』\]]\+\)[』\]]\]/[[\1]]/g'
80+ endif
81+
82+ " TODO: 半角单双引号无法有效判断起始和结束,以正确替换成全角单双引号。
83+ " 可以考虑通过标识符号提醒。
84+
85+ " 连续重复的标点符号规则
86+ if g: pangu_rule_duplicate_punctuation == 1
87+ " 连续的句号转成省略号
88+ " - `……`
89+ " - `⋯⋯`
90+ " - `......`
91+ " - `······`
92+ " @see [中文省略号应该垂直居中还是沉底?](https://www.zhihu.com/question/19593470)
93+ silent ! execute firstline . ' ,' . lastline . ' s/。\{3,}/....../g'
94+
95+ " #11: 根据《标点符号用法》,重复的感叹号、问号不允许超过 3 个。
96+ " [标点符号用法 GB/T 15834 2011](http://www.moe.gov.cn/ewebeditor/uploadfile/2015/01/13/20150113091548267.pdf)
97+ silent ! execute firstline . ' ,' . lastline . ' s/\([!?]\)\1\{3,}/\1\1\1/g'
98+ silent ! execute firstline . ' ,' . lastline . ' s/\([。,;:、“”『』〖〗《》]\)\1\{1,}/\1/g'
99+ endif
100+
101+ " 全角数字、英文字符、英文标点。
102+ if g: pangu_rule_fullwidth_alphabet == 1
103+ " 65248 是相对应的全角和半角的 Unicode 偏差。
104+ silent ! execute firstline . ' ,' . lastline . ' s/\([0-9A-Za-z@]\)/\=nr2char(char2nr(submatch(0))-65248)/g'
105+ endif
106+
107+ " 汉字与其前后的英文字符、英文标点、数字间增加空白。
108+ if g: pangu_rule_spacing == 1
109+ silent ! execute firstline . ' ,' . lastline . ' s/\([\u4e00-\u9fa5\u3040-\u30FF]\)\([a-zA-Z0-9@&=\[\$\%\^\-\+(\/\\]\)/\1 \2/g'
110+ silent ! execute firstline . ' ,' . lastline . ' s/\([a-zA-Z0-9!&;=\]\,\.\:\?\$\%\^\-\+\)\/\\]\)\([\u4e00-\u9fa5\u3040-\u30FF]\)/\1 \2/g'
111+ endif
112+
113+ if g: pangu_rule_trailing_whitespace == 1
114+ silent ! execute firstline . ' ,' . lastline . ' s/^ \[/[/'
115+ silent ! execute firstline . ' ,' . lastline . ' s/\s\+$//'
116+ endif
117+
118+ let ®expengine = l: save_regexpengine
119+ call setpos (" ." , savedpos)
77120endfunction
78121
79- function ! PanGuSpacing ()
80- if g: pangu_enabled == 1
81- call PanGuSpacingCore ()
122+ function ! PanGuSpacing (... )
123+ if g: pangu_enabled != 1
124+ return
125+ endif
126+
127+ let mode = " ALL"
128+ if exists (" a:1" )
129+ let mode = a: 1
82130 endif
131+
132+ call PanGuSpacingCore (mode )
83133endfunction
84134
85- command ! -nargs =* Pangu call PanGuSpacingCore ()
135+ command ! -nargs =* - range Pangu <line1> ,<line2> call PanGuSpacingCore (" RANGE" )
136+ command ! -nargs =* PanguAll call PanGuSpacingCore (" ALL" )
86137command ! -nargs =0 PanguDisable let g: pangu_enabled= 0
87138command ! -nargs =0 PanguEnable let g: pangu_enabled= 1
0 commit comments