xaizek / vim-includefixer (License: BSLv1) (since 2018-12-07)
Vim plugin to automatically categorize and alphabetize #include headers
Commit 101ea31ac5e5530c167c76d0e946b7245999eac4

Vim plugin for sorting includes in C/C++
Completed initial plugin
Author: Deon Poncini
Author date (UTC): 2013-12-15 00:08
Committer name: Deon Poncini
Committer date (UTC): 2013-12-15 00:08
Parent(s):
Signing key:
Tree: 20252ad960d196f65747ce5d1b2d9ed7ace8f8c0
File Lines added Lines deleted
.gitignore 2 0
LICENSE 0 0
README 0 0
doc/includefixer.txt 0 0
plugin/includefixer.vim 253 0
File .gitignore added (mode: 100644) (index 0000000..b72f9be)
1 *~
2 *.swp
File LICENSE added (mode: 100644) (index 0000000..e69de29)
File README added (mode: 100644) (index 0000000..e69de29)
File doc/includefixer.txt added (mode: 100644) (index 0000000..e69de29)
File plugin/includefixer.vim added (mode: 100644) (index 0000000..05d4979)
1 " includefixer.vim - Sorts C/C++ header files categorically
2 " Maintainer: Deon Poncini
3 " Version: 0.1
4
5 if exists('g:loaded_include_fixer')
6 finish
7 endif
8 let g:loaded_include_fixer = 1
9
10 let s:cstd = ["assert",
11 \ "ctype",
12 \ "errno",
13 \ "fenv",
14 \ "float",
15 \ "inttypes",
16 \ "iso646",
17 \ "limits",
18 \ "locale",
19 \ "math",
20 \ "setjmp",
21 \ "signal",
22 \ "stdarg",
23 \ "stdbool",
24 \ "stddef",
25 \ "stdint",
26 \ "stdio",
27 \ "stdlib",
28 \ "string",
29 \ "tgmath",
30 \ "time",
31 \ "uchar",
32 \ "wchar",
33 \ "wctype"]
34
35 let s:cxxstd = ["array",
36 \ "deque",
37 \ "forward_list",
38 \ "list",
39 \ "map",
40 \ "queue",
41 \ "set",
42 \ "stack",
43 \ "unordered_map",
44 \ "unordered_set",
45 \ "vector",
46 \ "fstream",
47 \ "iomanip",
48 \ "ios",
49 \ "iosfwd",
50 \ "iostream",
51 \ "istream",
52 \ "ostream",
53 \ "sstream",
54 \ "streambuf",
55 \ "atomic",
56 \ "condition_variable",
57 \ "future",
58 \ "mutex",
59 \ "thread",
60 \ "algorithm",
61 \ "bitset",
62 \ "chrono",
63 \ "codecvt",
64 \ "complex",
65 \ "exception",
66 \ "functional",
67 \ "initializer_list",
68 \ "iterator",
69 \ "limits",
70 \ "locale",
71 \ "memory",
72 \ "new",
73 \ "numeric",
74 \ "random",
75 \ "ratio",
76 \ "regex",
77 \ "stdexcept",
78 \ "string",
79 \ "system_error",
80 \ "tuple",
81 \ "typeindex",
82 \ "typeinfo",
83 \ "type_traits",
84 \ "utility",
85 \ "valarray"]
86
87 function! s:RecordIncludes(includes, lines)
88 call add(a:includes,getline("."))
89 call add(a:lines,line("."))
90 endfunction
91
92 function! s:ClearEmpty(start,end)
93 " delete every empty line between the start and end ranges of includes
94 if (line(".") < a:start)
95 return
96 elseif(line(".") >= a:end)
97 return
98 endif
99 execute 'delete _'
100 endfunction
101
102 function! s:IsModule(include, filename)
103 let l:mh = substitute(a:include,"include","","")
104 let l:mh = substitute(l:mh," ","","g")
105 let l:mh = substitute(l:mh,"#","","g")
106 let l:mh = substitute(l:mh,"\"","","g")
107 let l:mh = substitute(l:mh,"<","","")
108 let l:mh = substitute(l:mh,">","","")
109 let l:mh = substitute(l:mh,"[.].*","","")
110 " check if it is the module header
111 return l:mh ==# a:filename
112 endfunction
113
114 function! s:IsBoost(include)
115 return a:include =~# '[<"]boost/.*[>"]'
116 endfunction
117
118 function! s:IsQt(include)
119 return a:include =~# '[<"]Q[A-Zt].*[>"]'
120 endfunction
121
122 function! s:IsCStd(include)
123 for l:h in s:cstd
124 if a:include =~# '[<"]c'.l:h.'[>"]'
125 return 1
126 elseif a:include =~# '[<"]'.l:h.'\.h[>"]'
127 return 1
128 endif
129 endfor
130 return 0
131 endfunction
132
133 function! s:IsCxxStd(include)
134 for l:h in s:cxxstd
135 if a:include =~# '[<"]'.l:h.'[>"]'
136 return 1
137 endif
138 endfor
139 return 0
140 endfunction
141
142 function! s:SetupCustom(list)
143 if exists('g:include_fixer_custom') == 0
144 return
145 endif
146
147 let l:i = 0
148 while l:i < len(g:include_fixer_custom)
149 call add(a:list,[])
150 let l:i = l:i + 1
151 endwhile
152 endfunction
153
154 function! s:IsCustom(list, include)
155 if exists('g:include_fixer_custom') == 0
156 return 0
157 endif
158
159 let l:i = 0
160 while l:i < len(g:include_fixer_custom)
161 if a:include =~# g:include_fixer_custom[l:i]
162 call add(a:list[l:i],a:include)
163 return 1
164 endif
165 let l:i = l:i + 1
166 endwhile
167 return 0
168 endfunction
169
170 function! s:WriteOut(start,list)
171 " check the list is empty
172 if len(a:list) == 0
173 return a:start
174 endif
175
176 let l:end = a:start + len(a:list)
177
178 " sort the list
179 call sort(a:list)
180
181 " write out the list and an empty line
182 call append(a:start,a:list)
183 call append(l:end,"")
184 return l:end + 1
185 endfunction
186
187 function! s:FixIncludes()
188 " store the list of includes
189 let l:includes = []
190 let l:lines = []
191
192 " for each include, store it and delete it
193 %g/#include/call <SID>RecordIncludes(l:includes, l:lines)
194
195 if len(l:includes) == 0
196 return
197 endif
198
199 let l:start = l:lines[0] - 1
200 let l:end = l:lines[len(l:lines)-1]
201 %g/^\s*$/call <SID>ClearEmpty(l:start, l:end)
202 " now we can delete all the includes
203 %g/#include/d
204
205 " split and write out the includes
206 let l:module = []
207 let l:local = []
208 let l:boost = []
209 let l:qt = []
210 let l:cstd = []
211 let l:cxxstd = []
212 let l:custom = []
213 call <SID>SetupCustom(l:custom)
214
215 " get the filename without extension
216 let l:fr = substitute(expand('%:t'),"[.].*","","")
217
218 " iterate and sort
219 for l:i in l:includes
220 if <SID>IsModule(l:i,l:fr)
221 call add(l:module,l:i)
222 elseif <SID>IsBoost(l:i)
223 call add(l:boost,l:i)
224 elseif <SID>IsQt(l:i)
225 call add(l:qt,l:i)
226 elseif <SID>IsCStd(l:i)
227 call add(l:cstd,l:i)
228 elseif <SID>IsCxxStd(l:i)
229 call add(l:cxxstd,l:i)
230 elseif <SID>IsCustom(l:custom,l:i)
231 else
232 call add(l:local,l:i)
233 endif
234 endfor
235
236 " write out all the groups
237 let l:next = <SID>WriteOut(l:start,l:module)
238 let l:next = <SID>WriteOut(l:next,l:local)
239
240 let l:i = 0
241 while l:i < len(l:custom)
242 let l:next = <SID>WriteOut(l:next,l:custom[l:i])
243 let l:i = l:i + 1
244 endwhile
245
246 let l:next = <SID>WriteOut(l:next,l:boost)
247 let l:next = <SID>WriteOut(l:next,l:qt)
248 let l:next = <SID>WriteOut(l:next,l:cstd)
249 let l:next = <SID>WriteOut(l:next,l:cxxstd)
250
251 endfunction
252
253 command! FixIncludes call <SID>FixIncludes()
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vim-includefixer

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vim-includefixer

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master