0
|
1 " unreal.vim - Work with the Unreal Engine in Vim
|
|
2
|
|
3 " Utilities {{{
|
|
4
|
|
5 function! unreal#throw(message)
|
|
6 throw "unreal: ".a:message
|
|
7 endfunction
|
|
8
|
|
9 function! unreal#error(message)
|
|
10 let v:errmsg = "unreal: ".a:message
|
|
11 echoerr v:errmsg
|
|
12 endfunction
|
|
13
|
|
14 function! unreal#warning(message)
|
|
15 echohl WarningMsg
|
|
16 echom "unreal: ".a:message
|
|
17 echohl None
|
|
18 endfunction
|
|
19
|
|
20 function! unreal#info(message)
|
|
21 echom "unreal: ".a:message
|
|
22 endfunction
|
|
23
|
|
24 function! unreal#trace(message)
|
|
25 if g:unreal_trace
|
|
26 echom "unreal: ".a:message
|
|
27 endif
|
|
28 endfunction
|
|
29
|
|
30 if has('win32') || has('win64')
|
|
31 let s:iswin = 1
|
|
32 let s:dirsep = "\\"
|
|
33 let s:scriptext = ".bat"
|
|
34 else
|
|
35 let s:iswin = 0
|
|
36 let s:dirsep = "/"
|
|
37 let s:scriptext = ".sh"
|
|
38 endif
|
|
39
|
|
40 " }}}
|
|
41
|
|
42 " Modules {{{
|
|
43
|
|
44 function! unreal#call_modules(funcname, ...) abort
|
|
45 for module in g:unreal_modules
|
|
46 let l:fullfuncname = module.'#'.a:funcname
|
|
47 if exists('*'.l:fullfuncname)
|
|
48 call unreal#trace("Calling module function: ".l:fullfuncname)
|
|
49 call call(l:fullfuncname, a:000)
|
|
50 else
|
|
51 call unreal#trace("Skipping ".l:fullfuncname.": doesn't exist.")
|
|
52 endif
|
|
53 endfor
|
|
54 endfunction
|
|
55
|
|
56 " }}}
|
|
57
|
|
58 " Project Management {{{
|
|
59
|
|
60 function! unreal#find_project_dir() abort
|
|
61 if !empty(g:unreal_project_dir_finder)
|
|
62 return call(g:unreal_project_dir_finder)
|
|
63 endif
|
|
64
|
|
65 let l:path = getcwd()
|
|
66 try
|
|
67 let l:proj_dir = unreal#default_project_dir_finder(l:path)
|
|
68 catch /^unreal:/
|
|
69 let l:proj_dir = ''
|
|
70 endtry
|
|
71 call unreal#set_project_dir(l:proj_dir)
|
|
72 endfunction
|
|
73
|
|
74 function! unreal#default_project_dir_finder(path) abort
|
|
75 let l:cur = a:path
|
|
76 let l:prev = ""
|
|
77 while l:cur != l:prev
|
|
78 let l:markers = globpath(l:cur, g:unreal_project_dir_marker, 0, 1)
|
|
79 if !empty(l:markers)
|
|
80 call unreal#trace("Found marker file: ".l:markers[0])
|
|
81 return l:cur
|
|
82 endif
|
|
83 let l:prev = l:cur
|
|
84 let l:cur = fnamemodify(l:cur, ':h')
|
|
85 endwhile
|
|
86 call unreal#throw("No UE project markers found.")
|
|
87 endfunction
|
|
88
|
|
89 function! unreal#set_project_dir(project_dir, ...) abort
|
|
90 " Strip any end slashes on the directory path.
|
|
91 let g:unreal_project_dir = fnamemodify(a:project_dir, ':s?[/\\]$??')
|
|
92
|
|
93 let l:proj_was_set = !empty(g:unreal_project_dir)
|
|
94
|
|
95 if exists(":VimcrosoftSetSln")
|
|
96 if l:proj_was_set
|
|
97 let l:sln_files = glob(g:unreal_project_dir.s:dirsep."*.sln", 0, 1)
|
|
98 if !empty(l:sln_files)
|
|
99 execute "VimcrosoftSetSln ".fnameescape(l:sln_files[0])
|
|
100
|
|
101 call unreal#generate_vimcrosoft_extra_args(l:sln_files[0])
|
|
102 endif
|
|
103 else
|
|
104 execute "VimcrosoftUnsetSln"
|
|
105 endif
|
|
106 endif
|
|
107
|
|
108 if l:proj_was_set
|
|
109 call unreal#call_modules('on_project_changed', g:unreal_project_dir)
|
|
110 else
|
|
111 call unreal#call_modules('on_project_cleared')
|
|
112 endif
|
|
113
|
|
114 let l:silent = a:0 && a:1
|
|
115 if !l:silent
|
|
116 if l:proj_was_set
|
|
117 echom "UE Project set to: ".g:unreal_project_dir
|
|
118 else
|
|
119 echom "UE Project cleared"
|
|
120 endif
|
|
121 endif
|
|
122 endfunction
|
|
123
|
|
124 let s:extra_args_version = 1
|
|
125
|
|
126 function! unreal#generate_vimcrosoft_extra_args(solution) abort
|
|
127 let l:argfile =
|
|
128 \fnamemodify(a:solution, ':p:h').s:dirsep.
|
|
129 \'.vimcrosoft'.s:dirsep.
|
|
130 \fnamemodify(a:solution, ':t').'.flags'
|
|
131
|
|
132 let l:do_regen = 0
|
|
133 let l:version_line = "# version ".string(s:extra_args_version)
|
|
134 try
|
|
135 call unreal#trace("Checking for extra clang args file: ".l:argfile)
|
|
136 let l:lines = readfile(l:argfile)
|
|
137 if len(l:lines) < 1
|
|
138 call unreal#trace("Extra clang args file is empty... regenerating")
|
|
139 let l:do_regen = 1
|
|
140 elseif trim(l:lines[0]) != l:version_line
|
|
141 call unreal#trace("Extra clang args file is outdated... regenerating")
|
|
142 let l:do_regen = 1
|
|
143 endif
|
|
144 catch
|
|
145 call unreal#trace("Extra clang args file doesn't exist... regenerating")
|
|
146 let l:do_regen = 1
|
|
147 endtry
|
|
148 if l:do_regen
|
|
149 let l:arglines = [
|
|
150 \l:version_line,
|
|
151 \"-DUNREAL_CODE_ANALYZER"
|
|
152 \]
|
|
153 call writefile(l:arglines, l:argfile)
|
|
154 endif
|
|
155 endfunction
|
|
156
|
|
157 " }}}
|
|
158
|
|
159 " Commands {{{
|
|
160
|
|
161 function! unreal#generate_project_files() abort
|
|
162 call unreal#run_make("ugenprojfiles")
|
|
163 endfunction
|
|
164
|
|
165 function! unreal#set_platform(platform) abort
|
|
166 if index(g:unreal_platforms, a:platform) < 0
|
|
167 call unreal#throw("Invalid Unreal platform: ".a:platform)
|
|
168 endif
|
|
169 let g:unreal_project_platform = a:platform
|
|
170 endfunction
|
|
171
|
|
172 function! unreal#build(...) abort
|
|
173 let l:opts = copy(g:unreal_auto_build_options)
|
|
174 if a:0
|
|
175 let l:opts = a:000 + l:opts
|
|
176 endif
|
|
177 let g:unreal_temp_makeprg_args__ = l:opts
|
|
178 call unreal#run_make("ubuild")
|
|
179 endfunction
|
|
180
|
|
181 " }}}
|
|
182
|
|
183 " Completion Functions {{{
|
|
184
|
|
185 function! s:add_unique_suggestion_trailing_space(suggestions)
|
|
186 " If there's only one answer, add a space so we can start typing the
|
|
187 " next argument right away.
|
|
188 if len(a:suggestions) == 1
|
|
189 let a:suggestions[0] = a:suggestions[0] . ' '
|
|
190 endif
|
|
191 return a:suggestions
|
|
192 endfunction
|
|
193
|
|
194 function! s:filter_suggestions(arglead, suggestions)
|
|
195 let l:argpat = tolower(a:arglead)
|
|
196 let l:suggestions = filter(a:suggestions,
|
|
197 \{idx, val -> val =~? l:argpat})
|
|
198 return s:add_unique_suggestion_trailing_space(l:suggestions)
|
|
199 endfunction
|
|
200
|
|
201 function! unreal#complete_platforms(ArgLead, CmdLine, CursorPos)
|
|
202 return s:filter_suggestions(a:ArgLead, copy(g:unreal_platforms))
|
|
203 endfunction
|
|
204
|
|
205 function! unreal#complete_configs(ArgLead, CmdLine, CursorPos)
|
|
206 return s:filter_suggestions(a:ArgLead, copy(g:unreal_configurations))
|
|
207 endfunction
|
|
208
|
|
209 function! unreal#complete_build_targets(ArgLead, CmdLine, CursorPos)
|
|
210 let l:bits = split(a:CmdLine.'_', ' ')
|
|
211 let l:bits = l:bits[1:] " Remove the `UnrealBuild` command from the line
|
|
212 if len(l:bits) <= 1
|
|
213 let l:suggestions = vimcrosoft#get_sln_project_names()
|
|
214 elseif len(l:bits) == 2
|
|
215 let l:suggestions = copy(g:unreal_platforms)
|
|
216 elseif len(l:bits) == 3
|
|
217 let l:suggestions = copy(g:unreal_configurations)
|
|
218 elseif len(l:bits) >= 4
|
|
219 let l:suggestions = copy(g:unreal_build_options)
|
|
220 endif
|
|
221 return s:filter_suggestions(a:ArgLead, l:suggestions)
|
|
222 endfunction
|
|
223
|
|
224 " }}}
|
|
225
|
|
226 " Build System {{{
|
|
227
|
|
228 function! unreal#run_make(compilername) abort
|
|
229 execute "compiler ".a:compilername
|
|
230 if exists(':Make') " Support for vim-dispatch
|
|
231 Make
|
|
232 else
|
|
233 make
|
|
234 endif
|
|
235 endfunction
|
|
236
|
|
237 " }}}
|
|
238
|
|
239 " Unreal Scripts {{{
|
|
240
|
|
241 let s:builds_in_progress = []
|
|
242
|
|
243 function! unreal#get_script_path(scriptname, ...) abort
|
|
244 return g:unreal_project_dir.s:dirsep.a:scriptname.s:scriptext
|
|
245 endfunction
|
|
246
|
|
247 " }}}
|
|
248
|
|
249 " Initialization {{{
|
|
250
|
|
251 function! unreal#init() abort
|
|
252 if g:unreal_auto_find_project
|
|
253 call unreal#find_project_dir()
|
|
254 endif
|
|
255 endfunction
|
|
256
|
|
257 " }}}
|
|
258
|
|
259 " Statusline Functions {{{
|
|
260
|
|
261 function! unreal#statusline(...) abort
|
|
262 if empty(g:unreal_project_dir)
|
|
263 return ''
|
|
264 endif
|
|
265
|
|
266 let l:line = 'UE:'.g:unreal_project_dir
|
|
267 return l:line
|
|
268 endfunction
|
|
269
|
|
270 " }}}
|