├── README.md ├── after └── syntax │ └── swift.vim ├── autoload ├── swift.vim ├── swift │ ├── cache.vim │ ├── platform.vim │ └── util.vim └── unite │ └── sources │ └── swift.vim ├── doc └── swift.txt ├── ftdetect └── swift.vim ├── ftplugin └── swift.vim ├── indent └── swift.vim ├── plugin └── swift.vim ├── syntax └── swift.vim └── syntax_checkers └── swift └── swiftc.vim /README.md: -------------------------------------------------------------------------------- 1 | # Swift file type plugin for Vim 2 | 3 | This is a [Vim][] file type plugin for the [Swift][] programming language. 4 | 5 | [Vim]: http://www.vim.org 6 | [Swift]: https://developer.apple.com/swift/ 7 | 8 | ## Features 9 | 10 | * Full syntax coloring for Swift (including support for folding). 11 | * Helper commands for running Swift scripts and printing various compilation 12 | stages, including LLVM IR and assembly. 13 | * Full support for compiling/running iOS scripts using the iOS Simulator. 14 | * Supports multiple installations of Xcode. 15 | 16 | See [`:help ft-swift`][swift.txt] for more details. 17 | 18 | [swift.txt]: https://github.com/kballard/vim-swift/blob/master/doc/swift.txt 19 | 20 | ## Installation 21 | 22 | Install this plugin with your Vim plugin manager of choice. 23 | 24 | ### [NeoBundle][] 25 | 26 | [NeoBundle]: https://github.com/Shougo/neobundle.vim 27 | 28 | Add the following to your `.vimrc`: 29 | 30 | ```vim 31 | NeoBundle 'kballard/vim-swift', { 32 | \ 'filetypes': 'swift', 33 | \ 'unite_sources': ['swift/device', 'swift/developer_dir'] 34 | \} 35 | ``` 36 | 37 | ### [Pathogen][] 38 | 39 | [Pathogen]: https://github.com/tpope/vim-pathogen 40 | 41 | Run the following commands in your terminal: 42 | 43 | ```sh 44 | cd ~/.vim/bundle 45 | git clone https://github.com/kballard/vim-swift.git 46 | ``` 47 | -------------------------------------------------------------------------------- /after/syntax/swift.vim: -------------------------------------------------------------------------------- 1 | " File: after/syntax/swift.vim 2 | " Author: Kevin Ballard 3 | " Description: Conceal support for Swift 4 | " Last Change: June 26, 2014 5 | 6 | if !has('conceal') || &enc != 'utf-8' || get(b:, 'swift_no_conceal', get(g:, 'swift_no_conceal')) 7 | finish 8 | endif 9 | 10 | syn match swiftOperatorArrowHead contained '>' transparent contains=NONE conceal cchar=  11 | syn match swiftOperatorArrowTail contained '-' transparent contains=NONE conceal cchar=⟶ 12 | syn match swiftOperatorArrow '->\%([-/=+!*%<>&|^~.]\)\@!' contains=swiftOperatorArrowHead,swiftOperatorArrowTail transparent 13 | 14 | syn match swiftIdentPrime /\i\@<=__*\>/me=s+1 conceal cchar=′ containedin=swiftIdentifier transparent contains=NONE 15 | 16 | " vim: set et sw=4 ts=4: 17 | -------------------------------------------------------------------------------- /autoload/swift.vim: -------------------------------------------------------------------------------- 1 | " File: autoload/swift.vim 2 | " Author: Kevin Ballard 3 | " Description: Helper functions for Swift 4 | " Last Change: Feb 10, 2015 5 | 6 | " Run {{{1 7 | 8 | function! swift#Run(bang, args) 9 | let args = s:ShellTokenize(a:args) 10 | if a:bang 11 | let idx = index(l:args, '--') 12 | if idx != -1 13 | let swift_args = idx == 0 ? [] : l:args[:idx-1] 14 | let args = l:args[idx+1:] 15 | else 16 | let swift_args = l:args 17 | let args = [] 18 | endif 19 | else 20 | let swift_args = [] 21 | endif 22 | 23 | let b:swift_last_swift_args = copy(l:swift_args) 24 | let b:swift_last_args = copy(l:args) 25 | 26 | call s:WithPath(function("s:Run"), swift_args, args, a:bang, 0) 27 | endfunction 28 | 29 | function! s:Run(dict, swift_args, args, verbose, xctest) 30 | let exepath = a:dict.tmpdir.'/'.fnamemodify(a:dict.path, ':t:r') 31 | if has('win32') 32 | let exepath .= '.exe' 33 | endif 34 | 35 | let platformInfo = swift#platform#getPlatformInfo(swift#platform#detect()) 36 | if empty(platformInfo) 37 | return 38 | endif 39 | let swift_args = swift#platform#argsForPlatformInfo(platformInfo) 40 | let sourcepath = get(a:dict, 'tmpdir_relpath', a:dict.path) 41 | let swift_args += [sourcepath, '-o', exepath] + a:swift_args 42 | 43 | let swift = swift#xcrun('swiftc') 44 | 45 | let pwd = a:dict.istemp ? a:dict.tmpdir : '' 46 | let cmdstr = swift.' '.join(map(swift_args, 'shellescape(v:val)')) 47 | if a:verbose 48 | echo 'Compiling: ' . cmdstr 49 | endif 50 | let cmd = swift#util#system(cmdstr, pwd) 51 | if !empty(cmd.output) 52 | echohl WarningMsg 53 | for line in cmd.output 54 | echo line 55 | endfor 56 | echohl None 57 | endif 58 | if cmd.status == 0 59 | if a:xctest 60 | let path = swift#platform#xctestStringForExecutable(exepath, platformInfo) 61 | else 62 | let path = swift#platform#commandStringForExecutable(exepath, platformInfo) 63 | endif 64 | exe '!' . path . ' ' . join(map(a:args, 'shellescape(v:val)')) 65 | endif 66 | endfunction 67 | 68 | " Emit {{{1 69 | 70 | function! swift#Emit(tab, type, bang, args) 71 | let args = s:ShellTokenize(a:args) 72 | let type = a:type 73 | if type ==# 'sil' && a:bang 74 | let type = 'silgen' 75 | endif 76 | if type == 'objc-header' 77 | " objc-header generation saves some secondary files 78 | " so we should always use the temporary directory 79 | let save_write = &write 80 | set nowrite 81 | endif 82 | try 83 | call s:WithPath(function("s:Emit"), a:tab, type, args) 84 | finally 85 | if exists("save_write") | let &write = save_write | endif 86 | endtry 87 | endfunction 88 | 89 | function! s:Emit(dict, tab, type, args) 90 | try 91 | let platformInfo = swift#platform#getPlatformInfo(swift#platform#detect()) 92 | if empty(platformInfo) 93 | return 94 | endif 95 | let basename = fnamemodify(a:dict.path, ':t:r') 96 | let args = swift#platform#argsForPlatformInfo(platformInfo) 97 | if a:type == 'objc-header' 98 | " emitting the objc-header is a bit complicated 99 | " Swift 2 does not allow for emitting the header to stdout with - 100 | " (it actually does print it, but also prints an error), so we 101 | " need to write it to a file instead. 102 | let args += ['-emit-objc-header-path', a:dict.tmpdir.'/'.basename.'.h'] 103 | let args += ['-parse-as-library', '-emit-module'] 104 | " for some reason, even after all that, we still need to import an 105 | " obj-c header before it will emit anything useful. 106 | let args += ['-import-objc-header', '/dev/null'] 107 | " and finally, provide a path for the generated swiftmodule inside 108 | " the temporary dir, or it will put it in $PWD 109 | let args += ['-o', a:dict.tmpdir.'/'.basename.'.swiftmodule'] 110 | else 111 | let args += ['-emit-'.a:type, '-o', '-'] 112 | endif 113 | let args += a:args 114 | let args += ['--', get(a:dict, 'tmpdir_relpath', a:dict.path)] 115 | 116 | let swift = swift#xcrun('swiftc') 117 | 118 | let pwd = a:dict.istemp ? a:dict.tmpdir : '' 119 | let cmd = swift#util#system(swift.' '.join(map(args, 'shellescape(v:val)')), pwd) 120 | if cmd.status != 0 121 | echohl WarningMsg 122 | for line in cmd.output 123 | echo line 124 | endfor 125 | echohl None 126 | else 127 | if a:tab 128 | tabnew 129 | else 130 | new 131 | endif 132 | if a:type == 'objc-header' 133 | exe 'silent noautocmd keepalt read ++edit' fnameescape(a:dict.tmpdir.'/'.basename.'.h') 134 | else 135 | silent put =cmd.output 136 | endif 137 | 1 138 | d 139 | if a:type == 'ir' 140 | setl filetype=llvm 141 | let extension='ll' 142 | elseif a:type == 'assembly' 143 | setl filetype=asm 144 | let extension='s' 145 | elseif a:type == 'sil' || a:type == 'silgen' 146 | " we don't have a SIL filetype yet 147 | setl filetype= 148 | let extension='sil' 149 | elseif a:type == 'objc-header' 150 | setl filetype=objc 151 | let extension='h' 152 | endif 153 | setl buftype=nofile 154 | setl bufhidden=hide 155 | setl noswapfile 156 | if exists('l:extension') 157 | let suffix=1 158 | while 1 159 | let bufname = basename 160 | if suffix > 1 | let bufname .= ' ('.suffix.')' | endif 161 | let bufname .= '.'.extension 162 | if bufexists(bufname) 163 | let suffix += 1 164 | continue 165 | endif 166 | exe 'silent noautocmd keepalt file' fnameescape(bufname) 167 | break 168 | endwhile 169 | endif 170 | endif 171 | endtry 172 | endfunction 173 | 174 | " RunTests {{{1 175 | 176 | function! swift#RunTests(args) 177 | let args = s:ShellTokenize(a:args) 178 | call s:WithPath(function("s:Run"), args, [], 0, 1) 179 | endfunction 180 | 181 | " Version {{{1 182 | 183 | function! swift#PrintVersion() 184 | let cmd = swift#xcrun('swiftc', '-version') 185 | let output = system(l:cmd) 186 | let output = substitute(output, '\_s\+\%$', '', '') 187 | if v:shell_error == 0 188 | echo output 189 | else 190 | echohl ErrorMsg 191 | echo 'error running: '.l:cmd 192 | echohl None 193 | echo output 194 | endif 195 | endfunction 196 | 197 | " Utility functions {{{1 198 | 199 | " Invokes func(dict, ...) 200 | " Where {dict} is a dictionary with the following keys: 201 | " 'path' - The path to the file 202 | " 'tmpdir' - The path to a temporary directory that will be deleted when the 203 | " function returns. 204 | " 'istemp' - 1 if the path is a file inside of {dict.tmpdir} or 0 otherwise. 205 | " If {istemp} is 1 then an additional key is provided: 206 | " 'tmpdir_relpath' - The {path} relative to the {tmpdir}. 207 | " 208 | " {dict.path} may be a path to a file inside of {dict.tmpdir} or it may be the 209 | " existing path of the current buffer. If the path is inside of {dict.tmpdir} 210 | " then it is guaranteed to have a '.swift' extension. 211 | function! s:WithPath(func, ...) 212 | let buf = bufnr('') 213 | let saved = {} 214 | let dict = {} 215 | try 216 | let saved.write = &write 217 | set write 218 | let dict.path = expand('%') 219 | let pathisempty = empty(dict.path) 220 | 221 | " Always create a tmpdir in case the wrapped command wants it 222 | let dict.tmpdir = tempname() 223 | call mkdir(dict.tmpdir) 224 | 225 | if pathisempty || !saved.write 226 | let dict.istemp = 1 227 | " if we're doing this because of nowrite, preserve the filename 228 | if !pathisempty 229 | let filename = expand('%:t:r').".swift" 230 | else 231 | let filename = 'unnamed.swift' 232 | endif 233 | let dict.tmpdir_relpath = filename 234 | let dict.path = dict.tmpdir.'/'.filename 235 | 236 | let saved.mod = &mod 237 | set nomod 238 | 239 | try 240 | silent exe 'keepalt write! ' . fnameescape(dict.path) 241 | finally 242 | if pathisempty 243 | silent keepalt 0file 244 | endif 245 | endtry 246 | else 247 | let dict.istemp = 0 248 | update 249 | endif 250 | 251 | call call(a:func, [dict] + a:000) 252 | finally 253 | if bufexists(buf) 254 | for [opt, value] in items(saved) 255 | silent call setbufvar(buf, '&'.opt, value) 256 | unlet value " avoid variable type mismatches 257 | endfor 258 | endif 259 | if has_key(dict, 'tmpdir') | silent call s:RmDir(dict.tmpdir) | endif 260 | endtry 261 | endfunction 262 | 263 | function! swift#AppendCmdLine(text) 264 | call setcmdpos(getcmdpos()) 265 | let cmd = getcmdline() . a:text 266 | return cmd 267 | endfunction 268 | 269 | " Tokenize the String according to shell parsing rules 270 | function! s:ShellTokenize(text) 271 | let pat = '\%([^ \t\n''"]\+\|\\.\|''[^'']*\%(''\|$\)\|"\%(\\.\|[^"]\)*\%("\|$\)\)\+' 272 | let start = 0 273 | let tokens = [] 274 | while 1 275 | let pos = match(a:text, pat, start) 276 | if l:pos == -1 277 | break 278 | endif 279 | let end = matchend(a:text, pat, start) 280 | call add(tokens, strpart(a:text, pos, end-pos)) 281 | let start = l:end 282 | endwhile 283 | return l:tokens 284 | endfunction 285 | 286 | function! s:RmDir(path) 287 | " sanity check; make sure it's not empty, /, or $HOME 288 | if empty(a:path) 289 | echoerr 'Attempted to delete empty path' 290 | return 0 291 | elseif a:path == '/' || a:path == $HOME 292 | echoerr 'Attempted to delete protected path: ' . a:path 293 | return 0 294 | endif 295 | silent exe "!rm -rf " . shellescape(a:path) 296 | endfunction 297 | 298 | " Returns a string that can be passed to the shell to invoke xcrun 299 | " Optional arguments are escaped and joined with spaces to the string. 300 | function! swift#xcrun(...) 301 | let l:key = 'swift_developer_dir' 302 | let developer_dir = get(b:, l:key, get(w:, l:key, get(g:, l:key, ''))) 303 | if empty(developer_dir) 304 | let result = 'xcrun' 305 | else 306 | let result = 'env '.shellescape('DEVELOPER_DIR='.developer_dir).' xcrun' 307 | endif 308 | if a:0 > 0 309 | let result .= ' '.join(map(copy(a:000), 'shellescape(v:val)')) 310 | endif 311 | return result 312 | endfunction 313 | 314 | " }}}1 315 | 316 | " vim: set noet sw=4 ts=4: 317 | -------------------------------------------------------------------------------- /autoload/swift/cache.vim: -------------------------------------------------------------------------------- 1 | " File: swift/cache.vim 2 | " Author: Kevin Ballard 3 | " Description: In-memory cache for plist lookups. 4 | " Last Change: Jul 12, 2015 5 | 6 | if !exists('s:files') 7 | let s:files = {} 8 | endif 9 | 10 | " Usage: 11 | " swift#cache#read_plist_key({filename}, {key}) 12 | " Arguments: 13 | " {filename} - Path to the plist file to read. 14 | " {key} - A key, in the syntax accepted by PlistBuddy, to read. 15 | " Returns: 16 | " A string with the results. If no such plist/key combo exists, the empty 17 | " string will be returned. 18 | function! swift#cache#read_plist_key(filename, key) 19 | let l:file = get(s:files, a:filename, {}) 20 | if empty(l:file) 21 | let s:files[a:filename] = l:file 22 | endif 23 | if has_key(l:file, a:key) 24 | return l:file[a:key] 25 | endif 26 | let l:result = swift#util#system(['/usr/libexec/PlistBuddy', '-c', 'Print '.a:key, a:filename]) 27 | if l:result.status == 0 && !empty(l:result.output) 28 | let l:file[a:key] = l:result.output[0] 29 | else 30 | let l:file[a:key] = '' 31 | endif 32 | return l:file[a:key] 33 | endfunction 34 | 35 | " Usage: 36 | " swift#cache#clear_cache({filename}[, {key}]) 37 | " Arguments: 38 | " {filename} - Path to the plist file. 39 | " {key} - A key, in the syntax accepted by PlistBuddy. 40 | " Description: 41 | " If just {filename} is given, clears the cache for the entire file. If both 42 | " {filename} and {key} are given, clears the cache for just that pair. 43 | function! swift#cache#clear_cache(filename, ...) 44 | if has_key(s:files, a:filename) 45 | if a:0 > 1 46 | let l:file = s:files[a:filename] 47 | if has_key(l:file, a:1) 48 | unlet l:file[a:1] 49 | endif 50 | else 51 | unlet s:files[a:filename] 52 | endif 53 | endif 54 | endfunction 55 | -------------------------------------------------------------------------------- /autoload/swift/platform.vim: -------------------------------------------------------------------------------- 1 | " File: autoload/swift/platform.vim 2 | " Author: Kevin Ballard 3 | " Description: Platform support for Swift 4 | " Last Change: Jul 12, 2015 5 | 6 | " Returns a dict containing the following keys: 7 | " - platform - required, value is "macosx" or "iphonesimulator" 8 | " - device - optional, name of the device to use. Device may not be valid. 9 | function! swift#platform#detect() 10 | let dict = {} 11 | let check_file=1 12 | let iphoneos_platform_pat = '^i\%(phone\%(os\|sim\%(ulator\)\?\)\?\|pad\|os\)$' 13 | let macosx_platform_pat = '^\%(mac\)\?osx' 14 | for scope in [b:, w:, g:] 15 | if !has_key(dict, 'platform') 16 | let platform = get(scope, "swift_platform", "") 17 | if type(platform) == type("") 18 | if platform =~? iphoneos_platform_pat 19 | let dict.platform = 'iphonesimulator' 20 | elseif platform =~? macosx_platform_pat 21 | let dict.platform = 'macosx' 22 | endif 23 | endif 24 | endif 25 | if !has_key(dict, 'device') 26 | let device = get(scope, "swift_device", "") 27 | if type(device) == type("") && !empty(device) 28 | let dict.device = device 29 | endif 30 | endif 31 | if has_key(dict, 'platform') && has_key(dict, 'device') 32 | break 33 | endif 34 | if check_file 35 | let check_file = 0 36 | let limit = 128 37 | for scope in [b:, w:, g:] 38 | let value = get(scope, "swift_platform_detect_limit", "") 39 | if type(value) == type(0) 40 | let limit = value 41 | break 42 | endif 43 | endfor 44 | " look for a special comment of the form 45 | " // swift: platform=iphoneos 46 | " // swift: device=iPhone 6 47 | " or for an import of UIKit, AppKit, or Cocoa 48 | let commentnest = 0 49 | let autoplatform = '' 50 | for line in getline(1,limit) 51 | if line =~ '^\s*//\s*swift:' 52 | let start = matchend(line, '^\s*//\s*swift:\s*') 53 | let pat = '\(\w\+\)=\(\w\+\>\%(\s\w\+\>=\@!\)*\)' 54 | while 1 55 | let match = matchlist(line, pat, start) 56 | if empty(match) 57 | break 58 | endif 59 | let start += len(match[0]) 60 | if match[1] == 'platform' && !has_key(dict, 'platform') 61 | if match[2] =~? iphoneos_platform_pat 62 | let dict.platform = 'iphonesimulator' 63 | elseif match[2] =~? macosx_platform_pat 64 | let dict.platform = 'macosx' 65 | endif 66 | elseif match[1] == 'device' && !has_key(dict, 'device') 67 | let dict.device = match[2] 68 | endif 69 | endwhile 70 | endif 71 | if has_key(dict, 'platform') && has_key(dict, 'device') 72 | break 73 | endif 74 | if !empty(autoplatform) 75 | continue 76 | endif 77 | if commentnest == 0 78 | if line =~ '^\s*import\s\+UIKit\>' 79 | let autoplatform = 'iphonesimulator' 80 | elseif line =~ '^\s*import\s\+\%(AppKit\|Cocoa\)\>' 81 | let autoplatform = 'macosx' 82 | endif 83 | endif 84 | let start = 0 85 | while 1 86 | let start = match(line, '/\*\|\*/', start) 87 | if start < 0 | break | endif 88 | if line[start : start+1] == '/*' 89 | let commentnest+=1 90 | elseif commentnest > 0 91 | let commentnest-=1 92 | else 93 | " invalid syntax, cancel the whole line 94 | break 95 | endif 96 | let start += 1 97 | endwhile 98 | endfor 99 | endif 100 | endfor 101 | if !has_key(dict, 'platform') 102 | if empty(autoplatform) 103 | " autodetect failed, assume macosx 104 | let dict.platform = 'macosx' 105 | else 106 | let dict.platform = autoplatform 107 | endif 108 | endif 109 | return dict 110 | endfunction 111 | 112 | " Usage: 113 | " swift#platform#simDeviceInfo() 114 | " swift#platform#simDeviceInfo('runtimes') 115 | " Returns: 116 | " Dictionary with the following keys: 117 | " devices: [{ 118 | " name: The device name 119 | " uuid: The device UUID 120 | " type: Device identifier, e.g. "com.apple.CoreSimulator.SimDeviceType.iPhone-6" 121 | " state: Device state, e.g. "Shutdown" 122 | " runtime: { 123 | " name: Runtime name, e.g. "iOS 8.2" 124 | " version: Runtime version, e.g. "8.2" 125 | " build: Runtime build, e.g. "12D5452a" 126 | " identifier: Runtime identifier, e.g. "com.apple.CoreSimulator.SimRuntime.iOS-8-2" 127 | " } 128 | " }] 129 | " runtimes: [{ 130 | " name: Runtime name, e.g. "iOS 8.2" 131 | " version: Runtime version, e.g. "8.2" 132 | " build: Runtime build, e.g. "12D5452a" 133 | " identifier: Runtime identifier, e.g. "com.apple.CoreSimulator.SimRuntime.iOS-8-2" 134 | " }] 135 | " 136 | " If an error occurs with simctl, a message is echoed and {} is returned. 137 | " Unavailable devices are not returned. 138 | function! swift#platform#simDeviceInfo(...) 139 | let args = ['simctl', 'list'] 140 | if a:0 > 0 141 | call add(args, a:1) 142 | endif 143 | let cmd = swift#util#system(call('swift#xcrun', args)) 144 | if cmd.status 145 | redraw 146 | echohl ErrorMsg 147 | echom "Error: Shell command `xcrun simctl list` failed with error:" 148 | echohl None 149 | if has_key(cmd, 'stderr') 150 | for line in cmd.stderr 151 | echom line 152 | endfor 153 | else 154 | for line in cmd.output 155 | echom line 156 | endfor 157 | endif 158 | return {} 159 | endif 160 | 161 | let deviceTypes = {} 162 | let runtimes = {} 163 | let devices = [] 164 | let state = 0 165 | let deviceRuntime = '' 166 | for line in cmd.output 167 | if line == '' 168 | continue 169 | endif 170 | if line == '== Device Types ==' 171 | let state = 1 172 | elseif line == '== Runtimes ==' 173 | let state = 2 174 | elseif line == '== Devices ==' 175 | let state = 3 176 | elseif state == 1 " Device Types 177 | let matches = matchlist(line, '^\s*\(\w\&[^(]*\w\)\s\+(\([^)]*\))\s*$') 178 | if empty(matches) 179 | let state = -1 180 | else 181 | let deviceTypes[matches[1]] = matches[2] 182 | endif 183 | elseif state == 2 " Runtimes 184 | let matches = matchlist(line, '^\s*\(\w\&[^(]*\w\)\s\+(\([0-9.]\+\)\s*-\s*\([^)]\+\))\s\+(\([^)]*\))\%(\s\+(\([^)]*\))\)\?\s*$') 185 | if empty(matches) 186 | let state = -1 187 | elseif matches[5] =~? '^unavailable\>' 188 | " the runtime is unavailable 189 | " record it for now in case any devices show up for this 190 | " runtime, and filter it out after. 191 | let runtimes[matches[1]] = { 'unavailable': 1 } 192 | else 193 | let runtimes[matches[1]] = { 194 | \ 'name': matches[1], 195 | \ 'version': matches[2], 196 | \ 'build': matches[3], 197 | \ 'identifier': matches[4] 198 | \} 199 | endif 200 | elseif state == 3 " Devices 201 | if line =~ '^-- .* --$' 202 | let deviceRuntime = matchstr(line, '^-- \zs.*\ze --$') 203 | elseif empty(deviceRuntime) 204 | let state = -1 205 | elseif deviceRuntime =~? '^Unavailable:' 206 | " the runtime is unavailable, all devices in here will be 207 | " expected to similarly be unavailable. 208 | else 209 | let matches = matchlist(line, '^\s*\(\w\&[^(]*\w\)\s\+(\([^)]*\))\s\+(\([^)]*\))\%(\s\+(\([^)]*\))\)\?\s*$') 210 | if empty(matches) 211 | let state = -1 212 | elseif matches[4] =~? '^unavailable\>' 213 | " the device is unavailable 214 | else 215 | call add(devices, { 216 | \ 'name': matches[1], 217 | \ 'uuid': matches[2], 218 | \ 'state': matches[3], 219 | \ 'runtime': deviceRuntime 220 | \}) 221 | endif 222 | endif 223 | else 224 | let state = -1 225 | endif 226 | if state == -1 227 | redraw 228 | echohl ErrorMsg 229 | echom "Error: Unexpected output from shell command `xcrun simctl list`" 230 | echohl None 231 | echom line 232 | return {} 233 | endif 234 | endfor 235 | for device in devices 236 | let device.type = get(deviceTypes, device.name, '') 237 | let device.runtime = get(runtimes, device.runtime, {}) 238 | endfor 239 | return { 240 | \ 'devices': filter(devices, 'get(v:val.runtime, "unavailable", 0) == 0'), 241 | \ 'runtimes': filter(values(runtimes), 'get(v:val, "unavailable", 0) == 0') 242 | \} 243 | endfunction 244 | 245 | " Usage: 246 | " swift#platform#getPlatformInfo({platform}[, {synthesize}]) 247 | " Arguments: 248 | " {platform} - A platform dictionary as returned by swift#platform#detect() 249 | " {synthesize} - If 1, synthesize a result if the device is not set. 250 | " Returns: 251 | " A copy of {platform} augmented with a 'deviceInfo' key if relevant, 252 | " or {} if an error occurred (the error will be echoed). 253 | " 254 | " If the device is synthesized (when {synthesize} is 1), the 'deviceInfo' 255 | " key will not contain a 'type' or 'uuid' but will contain a key 256 | " 'synthesized' with the value 1. 257 | function! swift#platform#getPlatformInfo(platform, ...) 258 | if a:platform.platform == 'macosx' 259 | return copy(a:platform) 260 | elseif a:platform.platform == 'iphonesimulator' 261 | if empty(get(a:platform, 'device', {})) 262 | if get(a:, 1) 263 | " synthesize device info 264 | let allRuntimes = swift#platform#simDeviceInfo('runtimes') 265 | if empty(allRuntimes) 266 | return [] 267 | endif 268 | " use the runtime that corresponds to the SDK version if possible 269 | let runtime = {} 270 | let versionCmd = swift#util#system(swift#xcrun('-show-sdk-platform-version', '-sdk', a:platform.platform)) 271 | if versionCmd.status == 0 && !empty(versionCmd.output) 272 | for elem in allRuntimes.runtimes 273 | if elem.version == versionCmd.output[0] 274 | let runtime = elem 275 | break 276 | endif 277 | endfor 278 | endif 279 | if empty(runtime) 280 | " can't find a matching runtime? Pick the highest-numbered 281 | " one. SDK numbers should be just major.minor so we can 282 | " compare them as floats. 283 | for elem in allRuntimes.runtimes 284 | if empty(runtime) || str2float(elem.version) > str2float(runtime.version) 285 | let runtime = elem 286 | endif 287 | endfor 288 | if empty(runtime) 289 | redraw 290 | echohl ErrorMsg 291 | echo "Error: Can't find any valid iOS Simulator runtimes" 292 | echohl None 293 | return [] 294 | endif 295 | endif 296 | let deviceInfo = { 297 | \ 'name': 'Synthesized Device', 298 | \ 'runtime': runtime, 299 | \ 'arch': 'x86_64' 300 | \} 301 | return extend(copy(a:platform), {'deviceInfo': deviceInfo}) 302 | else 303 | redraw 304 | echohl ErrorMsg 305 | echom "Error: No device specified for platform iphonesimulator" 306 | echohl None 307 | echo "Please set " 308 | echohl Identifier | echon "b:swift_device" | echohl None 309 | echon " or " 310 | echohl Identifier | echon "g:swift_device" | echohl None 311 | echon " and try again." 312 | if swift#util#has_unite() 313 | echo "Type `" 314 | echohl PreProc 315 | echon ":Unite swift/device" 316 | echohl None 317 | echon "` to select a device." 318 | endif 319 | return [] 320 | end 321 | endif 322 | let allDeviceInfo = swift#platform#simDeviceInfo() 323 | if empty(allDeviceInfo) 324 | return [] 325 | endif 326 | let deviceInfo={} 327 | let found=0 328 | for deviceInfo in allDeviceInfo.devices 329 | if deviceInfo.name ==? a:platform.device || deviceInfo.uuid ==? a:platform.device 330 | let found=1 331 | break 332 | endif 333 | endfor 334 | if !found 335 | redraw 336 | echohl ErrorMsg 337 | echom "Error: Device '".a:platform.device."' does not exist." 338 | echohl None 339 | return [] 340 | endif 341 | return extend(copy(a:platform), {'deviceInfo': deviceInfo}) 342 | else 343 | throw "swift: unexpected platform ".a:platform.platform 344 | endif 345 | endfunction 346 | 347 | " Arguments: 348 | " {platform} - A platform info dictionary as returned by 349 | " swift#platform#getPlatformInfo() 350 | " Returns: 351 | " A List of arguments to be passed to swiftc. If the device is invalid 352 | " or another error occurred, an error is echoed and [] is returned. 353 | function! swift#platform#argsForPlatformInfo(platformInfo) 354 | let sdkInfo = swift#platform#sdkInfo(a:platformInfo.platform) 355 | let args = ['-sdk', sdkInfo.path] 356 | " add the SDKPlatformPath/Developer/Library/Frameworks so XCTest works 357 | let devFrameworks = sdkInfo.platformPath . '/Developer/Library/Frameworks' 358 | let args += ['-F', devFrameworks] 359 | let args += ['-Xlinker', '-rpath', '-Xlinker', devFrameworks] 360 | " We also need -lswiftCore or xctest will crash when running it, I don't 361 | " know why. This should be harmless when not using xctest. 362 | let args += ['-lswiftCore'] 363 | if a:platformInfo.platform == 'macosx' 364 | return args 365 | elseif a:platformInfo.platform == 'iphonesimulator' 366 | let deviceInfo = a:platformInfo.deviceInfo 367 | if get(deviceInfo, 'synthesized') 368 | let arch = '' 369 | else 370 | let profile_plist = sdkInfo.platformPath . '/Developer/Library/CoreSimulator/Profiles/DeviceTypes/' 371 | let profile_plist .= deviceInfo.name . '.simdevicetype/Contents/Resources/profile.plist' 372 | let arch = swift#cache#read_plist_key(profile_plist, 'supportedArchs:0') 373 | endif 374 | if empty(arch) 375 | let arch = 'x86_64' 376 | endif 377 | let target = arch.'-apple-ios'.deviceInfo.runtime.version 378 | return extend(args, ['-target', target]) 379 | else 380 | throw "swift: unexpected platform ".a:platformInfo.platform 381 | endif 382 | endfunction 383 | 384 | " Returns a dictionary with information about the current SDK with keys: 385 | " path - String - The SDK path. 386 | " platformPath - String - The SDK platform path. 387 | " The dictionary values may be "" if an error occurs. 388 | function! swift#platform#sdkInfo(sdkname) 389 | " it's actually faster to run xcrun twice than to run xcodebuild once. 390 | let pathCmd = swift#util#system(swift#xcrun('-show-sdk-path', '-sdk', a:sdkname)) 391 | let platformPathCmd = swift#util#system(swift#xcrun('-show-sdk-platform-path', '-sdk', a:sdkname)) 392 | return { 393 | \ 'path': pathCmd.status != 0 || empty(pathCmd.output) ? "" : pathCmd.output[0], 394 | \ 'platformPath': platformPathCmd.status != 0 || empty(platformPathCmd.output) ? 395 | \ "" : platformPathCmd.output[0] 396 | \} 397 | endfunction 398 | 399 | " Arguments: 400 | " {exepath} - Path to an executable 401 | " {platformInfo} - Platform info 402 | " Returns: 403 | " A string that can be passed to ! to execute the binary. 404 | function! swift#platform#commandStringForExecutable(exepath, platformInfo) 405 | if a:platformInfo.platform ==# 'iphonesimulator' 406 | return swift#xcrun('simctl', 'spawn', a:platformInfo.deviceInfo.uuid, a:exepath) 407 | else 408 | return shellescape(a:exepath) 409 | endif 410 | endfunction 411 | 412 | " Arguments: 413 | " {exepath} - Path to an executable 414 | " {platformInfo} - Platform Info 415 | " Returns: 416 | " A string that can be passed to ! to run the binary with xctest. 417 | function! swift#platform#xctestStringForExecutable(exepath, platformInfo) 418 | return swift#xcrun('-sdk', a:platformInfo.platform, 'xctest', a:exepath) 419 | endfunction 420 | -------------------------------------------------------------------------------- /autoload/swift/util.vim: -------------------------------------------------------------------------------- 1 | " File: swift/util.vim 2 | " Author: Kevin Ballard 3 | " Description: Utilities for the Swift filetype plugin 4 | " Last Change: Feb 11, 2015 5 | 6 | " Returns 1 if vimproc is available 7 | function! swift#util#has_vimproc() 8 | if !exists('*vimproc#version') 9 | try 10 | call vimproc#version() 11 | catch 12 | endtry 13 | endif 14 | return exists('*vimproc#version') 15 | endfunction 16 | 17 | " Returns 1 if unite is available 18 | function! swift#util#has_unite() 19 | if !exists('*unite#version') 20 | try 21 | call unite#version() 22 | catch 23 | endtry 24 | endif 25 | return exists('*unite#version') 26 | endfunction 27 | 28 | " Usage: 29 | " swift#util#system({cmd}[, {pwd}]) 30 | " swift#util#system({args}[, {pwd}]) 31 | " Arguments: 32 | " {cmd} - String - A command suitable for executing. 33 | " {args} - List - A list of command and arguments. 34 | " {pwd} - String - Optional - A directory to run the command from. 35 | " Returns: 36 | " A dictionary with the following keys: 37 | " status - The exit status. 38 | " output - List - The combined stdout and stderr lines. 39 | " stderr - List - Optional - The stderr lines. Only present if vimproc is 40 | " installed. 41 | if swift#util#has_vimproc() 42 | function! swift#util#system(args, ...) 43 | if type(a:args) == type('') 44 | let l:args = vimproc#parser#split_args(a:args) 45 | else 46 | let l:args = a:args 47 | endif 48 | if a:0 > 0 && !empty(a:1) 49 | " vimproc can't handle `cd dir && cmd` because it's not a shell, so it's 50 | " probably invoking /usr/bin/cd. But we can run sh, have it change 51 | " directories for us, and then execute the real command. 52 | let l:args = extend(['sh', '-c', 'cd "$1" && shift && exec "$@"', '--', a:1], l:args) 53 | endif 54 | let restore_popen2_cmd = 0 55 | if exists('g:vimproc#popen2_commands') 56 | let restore_popen2_cmd = get(g:vimproc#popen2_commands, 'sh', 0) 57 | if restore_popen2_cmd 58 | let g:vimproc#popen2_commands['sh'] = 0 59 | endif 60 | endif 61 | try 62 | let output = vimproc#system(l:args) 63 | let status = vimproc#get_last_status() 64 | let errmsg = vimproc#get_last_errmsg() 65 | finally 66 | if restore_popen2_cmd 67 | let g:vimproc#popen2_commands['sh'] = restore_popen2_cmd 68 | endif 69 | endtry 70 | let outlines = split(output, '\r*\n', 1) 71 | if !empty(outlines) && empty(outlines[-1]) 72 | call remove(outlines, -1) 73 | endif 74 | let errlines = split(errmsg, '\r*\n', 1) 75 | if !empty(errlines) && empty(errlines[-1]) 76 | call remove(errlines, -1) 77 | endif 78 | return { 'status': status, 'output': outlines, 'stderr': errlines } 79 | endfunction 80 | else 81 | function! swift#util#system(args, ...) 82 | if type(a:args) == type([]) 83 | let l:cmd = join(map(a:args, 'shellescape(v:val)'), ' ') 84 | else 85 | let l:cmd = a:args 86 | endif 87 | if a:0 > 0 && !empty(a:1) 88 | let l:cmd = 'cd ' . shellescape(a:1) . ' && ' . l:cmd 89 | endif 90 | let output = system(l:cmd) 91 | let status = v:shell_error 92 | let lines = split(output, '\r*\n', 1) 93 | if !empty(lines) && empty(lines[-1]) 94 | call remove(lines, -1) 95 | endif 96 | return { 'status': status, 'output': lines } 97 | endfunction 98 | endif 99 | " vim: set et sw=2 ts=2: 100 | -------------------------------------------------------------------------------- /autoload/unite/sources/swift.vim: -------------------------------------------------------------------------------- 1 | " File: unite/sources/swift.vim 2 | " Author: Kevin Ballard 3 | " Description: Unite sources file for Swift 4 | " Last Change: Jul 12, 2015 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | function! unite#sources#swift#define() "{{{ 10 | let sources = [s:source_device] 11 | if !empty(s:source_dev_dir) 12 | call add(sources, s:source_dev_dir) 13 | endif 14 | return sources 15 | endfunction "}}} 16 | 17 | " swift/device {{{ 18 | 19 | let s:source_device = { 20 | \ 'name': 'swift/device', 21 | \ 'hooks': {}, 22 | \ 'action_table': {}, 23 | \ 'default_action': 'set_global', 24 | \ 'is_grouped': 1, 25 | \ 'description': 'iOS Simulator devices for use with Swift' 26 | \} 27 | 28 | function! s:source_device.gather_candidates(args, context) "{{{ 29 | let deviceInfo = swift#platform#simDeviceInfo() 30 | if empty(deviceInfo) 31 | redraw 32 | call unite#print_source_error('Error fetching sim device info', self.name) 33 | return [] 34 | endif 35 | return map(copy(deviceInfo.devices), "{ 'word': v:val.uuid, 'abbr': v:val.name, 'group': v:val.runtime.name }") 36 | endfunction "}}} 37 | 38 | function! s:source_device.hooks.on_post_filter(args, context) "{{{ 39 | let g:swift_unite_candidates = deepcopy(a:context.candidates) 40 | for candidate in a:context.candidates 41 | if get(candidate, 'is_dummy') 42 | " group name 43 | let candidate.abbr = 44 | \ '-- ' . candidate.word . ' --' 45 | else 46 | let candidate.abbr = 47 | \ ' ' . candidate.abbr 48 | endif 49 | endfor 50 | endfunction "}}} 51 | 52 | " Actions {{{ 53 | 54 | let s:source_device.action_table.set_buffer = { 55 | \ 'description': 'select the iOS Simulator device (buffer-local)', 56 | \ 'is_selectable': 0 57 | \} 58 | function! s:source_device.action_table.set_buffer.func(candidate) "{{{ 59 | let b:swift_device = a:candidate.word 60 | endfunction "}}} 61 | 62 | let s:source_device.action_table.set_global = { 63 | \ 'description': 'select the iOS Simulator device (global)', 64 | \ 'is_selectable': 0 65 | \} 66 | function! s:source_device.action_table.set_global.func(candidate) "{{{ 67 | let g:swift_device = a:candidate.word 68 | endfunction "}}} 69 | 70 | " }}} 71 | 72 | " }}} 73 | " swift/developer_dir {{{ 74 | 75 | let s:source_dev_dir = { 76 | \ 'name': 'swift/developer_dir', 77 | \ 'hooks': {}, 78 | \ 'action_table': {}, 79 | \ 'default_action': 'set_global', 80 | \ 'description': 'Xcode directories for use with Swift' 81 | \} 82 | 83 | function! s:source_dev_dir.gather_candidates(args, context) "{{{ 84 | if !swift#util#has_vimproc() 85 | call unite#print_source_message('vimproc plugin is not installed.', self.name) 86 | return [] 87 | endif 88 | let cmd = swift#util#system('mdfind "kMDItemCFBundleIdentifier = com.apple.dt.Xcode"') 89 | if cmd.status == 0 90 | let result = [{'word': '', 'abbr': '(default)'}] 91 | call extend(result, map(cmd.output, "{ 'word': v:val }")) 92 | return result 93 | else 94 | call unite#print_source_error('mdfind error', self.name) 95 | for line in cmd.output 96 | call unite#print_source_error(line, self.name) 97 | endfor 98 | return [] 99 | endif 100 | endfunction "}}} 101 | 102 | " Actions {{{ 103 | 104 | let s:source_dev_dir.action_table.set_buffer = { 105 | \ 'description': 'select the Swift developer dir (buffer-local)', 106 | \ 'is_selectable': 0 107 | \} 108 | function! s:source_dev_dir.action_table.set_buffer.func(candidate) "{{{ 109 | if empty(a:candidate.word) 110 | unlet! b:swift_developer_dir 111 | else 112 | let b:swift_developer_dir = a:candidate.word 113 | endif 114 | endfunction "}}} 115 | 116 | let s:source_dev_dir.action_table.set_global = { 117 | \ 'description': 'select the Swift developer dir (global)', 118 | \ 'is_selectable': 0 119 | \} 120 | function! s:source_dev_dir.action_table.set_global.func(candidate) "{{{ 121 | if empty(a:candidate.word) 122 | unlet! g:swift_developer_dir 123 | else 124 | let g:swift_developer_dir = a:candidate.word 125 | endif 126 | endfunction "}}} 127 | 128 | " }}} 129 | 130 | " }}} 131 | 132 | let &cpo = s:save_cpo 133 | unlet s:save_cpo 134 | -------------------------------------------------------------------------------- /doc/swift.txt: -------------------------------------------------------------------------------- 1 | *swift.txt* Filetype plugin for Swift 2 | 3 | ============================================================================== 4 | CONTENTS *swift* *ft-swift* 5 | 6 | 1. Introduction |swift-intro| 7 | 2. Settings |swift-settings| 8 | 3. Commands |swift-commands| 9 | 4. Mappings |swift-mappings| 10 | 5. Unite Sources |swift-unite-sources| 11 | 6. FAQ |swift-faq| 12 | 13 | ============================================================================== 14 | INTRODUCTION *swift-intro* 15 | 16 | This plugin provides syntax and supporting functionality for the Swift 17 | filetype. 18 | 19 | ============================================================================== 20 | SETTINGS *swift-settings* 21 | 22 | This plugin has variables you can define in your vimrc that change the 23 | behavior of the plugin. 24 | 25 | *g:swift_no_conceal* 26 | g:swift_no_conceal~ 27 | Type: Number 28 | Set this option to turn off |conceal| support: > 29 | let g:swift_no_conceal = 1 30 | < 31 | *g:swift_no_fold* 32 | g:swift_no_fold~ 33 | Type: Number 34 | Set this option to turn off |folding|: > 35 | let g:swift_no_fold = 1 36 | < 37 | Value Effect ~ 38 | 0 Folding is enabled. All folds are open by default. 39 | 1 Folding is enabled. 'foldlevel' is reset to the global 40 | value (all folds are closed by default). 41 | 2 Folding is not enabled. 'foldmethod' and 'foldlevel' 42 | are both left at their current values. 43 | 44 | *g:swift_developer_dir* 45 | g:swift_developer_dir~ 46 | Type: String 47 | Set this option to a path to use for DEVELOPER_DIR: > 48 | let g:swift_developer_dir='/Applications/Xcode-Beta.app' 49 | < 50 | This option may also be specified as *w:swift_developer_dir* or 51 | *b:swift_developer_dir* 52 | 53 | If unset, the default developer dir is used (see `xcode-select`). 54 | 55 | *g:swift_platform* 56 | g:swift_platform~ 57 | Type: String 58 | Set this option to the platform to compile the code for. 59 | Possible values are "macosx" and "iphonesimulator": > 60 | let g:swift_platform = 'macosx' 61 | < 62 | This option may also be specified as *w:swift_platform* or 63 | *b:swift_platform* 64 | 65 | If |g:swift_platform| is unset, this option can be inferred from a 66 | comment in the file of the form: > 67 | // swift: platform=iphonesimulator 68 | < 69 | If unset, and if no comment is found as described above, if the file 70 | includes an import for the 'UIKit' framework it is assumed to be 71 | "iphonesimulator", and if the file includes an import for the 'AppKit' 72 | or 'Cocoa' frameworks it is assumed to be "macosx". 73 | 74 | If no value is set or inferred, it defaults to "macosx". 75 | 76 | *g:swift_device* 77 | g:swift_device~ 78 | Type: String 79 | The name of the configured iOS Simulator device to use when running 80 | code for the "iphonesimulator" platform: > 81 | let g:swift_device = 'iPhone 6' 82 | < 83 | This option can also be specified as *w:swift_device* or 84 | *b:swift_device* 85 | 86 | Like |g:swift_platform|, this option can be inferred from a comment of 87 | the form: > 88 | // swift: device=iPhone 6 89 | < 90 | If unset, attempting to run code for the "iphonesimulator" platform 91 | will fail. 92 | 93 | *g:swift_platform_detect_limit* 94 | g:swift_platform_detect_limit~ 95 | Type: Number 96 | This option defines the number of lines that are scanned in order to 97 | detect the platform if |g:swift_platform| is unset: > 98 | let g:swift_platform_detect_limit = 20 99 | < 100 | This option can also be specified as *w:swift_platform_detect_limit* 101 | or *b:swift_platform_detect_limit* 102 | 103 | The default value is 128. 104 | 105 | *g:swift_suppress_showmatch_warning* 106 | g:swift_suppress_showmatch_warning~ 107 | Type: Number 108 | Set this option to suppress the warning about using 'showmatch'. This 109 | option is automatically set after the warning is displayed once to 110 | prevent it from showing multiple times. > 111 | let g:swift_suppress_showmatch_warning = 1 112 | < 113 | ============================================================================== 114 | COMMANDS *swift-commands* 115 | 116 | :SwiftRun [args] *:SwiftRun* 117 | :SwiftRun! [swift-args] [-- [args]] 118 | Compiles and runs the current file. If it has unsaved changes, 119 | it will be saved first using |:update|. If the current file is 120 | an unnamed buffer, it will be written to a temporary file 121 | first. The compiled binary is always placed in a temporary 122 | directory, but it is run from the current directory. 123 | 124 | The arguments given to |:SwiftRun| will be passed to the 125 | compiled binary. 126 | 127 | If ! is specified, the arguments are passed to swiftc instead. 128 | A "--" argument will separate the compiler arguments from the 129 | arguments passed to the binary. When using ! the compiler 130 | invocation will be echoed before the program output. 131 | 132 | :SwiftEmitIr [args] *:SwiftEmitIr* 133 | Compiles the current file to LLVM IR and displays the results 134 | in a new split. If the current file has unsaved changes, it 135 | will be saved first using |:update|. If the current file is an 136 | unnamed buffer, it will be written to a temporary file first. 137 | 138 | The arguments given to |:SwiftEmitIr| will be passed to 139 | swiftc. 140 | 141 | :TabSwiftEmitIr [args] *:TabSwiftEmitIr* 142 | Same as |:SwiftEmitIr| but the results are displayed in a new 143 | tab instead. 144 | {not available when the |+windows| feature was disabled at 145 | compile time} 146 | 147 | :SwiftEmitSil [args] *:SwiftEmitSil* 148 | :SwiftEmitSil! [args] 149 | Compiles the current file to SIL and displays the results in a 150 | new split. If the current file has unsaved changes, it will be 151 | saved first using |:update|. If the current file is an unnamed 152 | buffer, it will be written to a temporary file first. 153 | 154 | The arguments given to |:SwiftEmitSil| will be passed to 155 | swiftc. 156 | 157 | If ! is specified, raw SIL will be emitted instead of 158 | canonical SIL. 159 | 160 | :TabSwiftEmitSil [args] *:TabSwiftEmitSil* 161 | :TabSwiftEmitSil! [args] 162 | Same as |:SwiftEmitSil| but the results are displayed in a new 163 | tab instead. 164 | {not available when the |+windows| feature was disabled at 165 | compile time} 166 | 167 | :SwiftEmitAsm [args] *:SwiftEmitAsm* 168 | Compiles the current file to assembly and displays the results 169 | in a new split. If the current file has unsaved changes, it 170 | will be saved first using |:update|. If the current file is an 171 | unnamed buffer, it will be written to a temporary file first. 172 | 173 | The arguments given to |:SwiftEmitAsm| will be passed to 174 | swiftc. 175 | 176 | :TabSwiftEmitAsm [args] *:TabSwiftEmitAsm* 177 | Same as |:SwiftEmitAsm| but the results are displayed in a new 178 | tab instead. 179 | {not available when the |+windows| feature was disabled at 180 | compile time} 181 | 182 | :SwiftEmitHeader [args] *:SwiftEmitHeader* 183 | Compiles the current file and displays a synthesized 184 | Objective-C header in a new split. The current file will 185 | always be written to a temporary buffer first. 186 | 187 | The arguments given to |:SwiftEmitHeader| will be passed to 188 | swiftc. 189 | 190 | :TabSwiftEmitHeader [args] *:TabSwiftEmitHeader* 191 | Same as |:SwiftEmitHeader| but the results are displayed in a 192 | new tab instead. 193 | {not available when the |+windows| feature was disabled at 194 | compile time} 195 | 196 | :SwiftRunTests [args] *:SwiftRunTests* 197 | Compiles the current file and runs it using the `xctest` test 198 | runner. 199 | 200 | The arguments given to |:SwiftRunTests| will be passed to 201 | swiftc. 202 | 203 | Note: This seems to work when all the tests pass, but failed 204 | test assertions cause the test runner to exit with code 11. I 205 | don't know what's going on. This also doesn't seem to work 206 | with iOS files. 207 | 208 | :SwiftVersion *:SwiftVersion* 209 | Prints the current Swift compiler version. 210 | 211 | ============================================================================== 212 | MAPPINGS *swift-mappings* 213 | 214 | *swift_* 215 | Executes |:SwiftRun| with no arguments. 216 | Note: This binding is only available in MacVim. 217 | 218 | *swift_* 219 | Populates the command line with |:SwiftRun|! using the 220 | arguments given to the last invocation, but does not 221 | execute it. 222 | Note: This binding is only available in MacVim. 223 | 224 | ============================================================================== 225 | UNITE SOURCES *swift-unite-sources* 226 | 227 | If you have |unite| installed, a source is provided for picking the iOS 228 | Simulator device to use. 229 | 230 | |unite|: http://github.com/Shougo/unite.vim 231 | 232 | swift/device *swift-unite-source-swift-device* 233 | Candidates are all available iOS Simulator devices. The 234 | default action is to set |g:swift_device|. 235 | 236 | swift/developer_dir *swift-unite-source-swift-developer_dir* 237 | Note: Requires |vimproc|. 238 | Candidates are the available Xcode installations on the 239 | system. The default action is to set |g:swift_developer_dir|. 240 | 241 | ============================================================================== 242 | FAQ *swift-faq* 243 | 244 | Q: When I run |:SwiftRun| or press , why do I get the following message? 245 | > 246 | Error: no device specified for platform iphonesimulator 247 | Please set b:swift_device or g:swift_device and try again. 248 | < 249 | A: Either you've set |g:swift_platform| to "iphonesimulator" or it's unset and 250 | the current file contains > 251 | import UIKit 252 | < 253 | Under these conditions, the plugin will attempt to compile for the iOS 254 | Simulator instead of for OS X. In order to run the program in the iOS 255 | Simulator, it needs to know which simulator device to use. See 256 | |g:swift_device| for details. 257 | 258 | ============================================================================== 259 | vim:ft=help:tw=78:sw=4:noet:ts=8:norl: 260 | -------------------------------------------------------------------------------- /ftdetect/swift.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.swift setf swift 2 | -------------------------------------------------------------------------------- /ftplugin/swift.vim: -------------------------------------------------------------------------------- 1 | " File: ftplugin/swift.vim 2 | " Author: Kevin Ballard 3 | " Description: Filetype plugin for Swift 4 | " Last Change: Jul 12, 2015 5 | 6 | if exists("b:did_ftplugin") 7 | finish 8 | endif 9 | let b:did_ftplugin = 1 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | " Settings {{{1 15 | 16 | " Match Xcode default indentation settings 17 | setlocal expandtab shiftwidth=4 tabstop=4 softtabstop=4 18 | 19 | " Use 80 as the text width but only format comments 20 | setlocal textwidth=80 21 | setlocal formatoptions-=t formatoptions+=croqnl 22 | silent! setlocal formatoptions+=j 23 | 24 | " cc=+1 is common, but showing it for the comment width kind of sucks. 25 | " Let's pick 120 characters instead, that's a good length. 26 | setlocal colorcolumn=121 27 | 28 | setlocal suffixesadd=.swift 29 | 30 | setlocal comments=s1:/**,mb:*,ex:*/,s1:/*,mb:*,ex:*/,:///,:// 31 | setlocal commentstring=//%s 32 | 33 | let s:fold = has("folding") ? get(b:, 'swift_no_fold', get(g:, 'swift_no_fold')) : 0 34 | if s:fold != 2 35 | if s:fold == 1 36 | setlocal foldmethod=syntax 37 | setlocal foldlevel< 38 | else 39 | setlocal foldmethod=syntax 40 | setlocal foldlevel=999 41 | endif 42 | let b:swift__did_set_fold=1 43 | endif 44 | unlet s:fold 45 | 46 | let s:conceal = has('conceal') ? get(b:, 'swift_no_conceal', get(g:, 'swift_no_conceal')) : 0 47 | if !s:conceal 48 | setlocal conceallevel=2 49 | let b:swift__did_set_conceallevel=1 50 | endif 51 | unlet s:conceal 52 | 53 | 54 | " Commands {{{1 55 | 56 | " See |:SwiftRun| for docs 57 | command! -nargs=* -complete=file -buffer -bang SwiftRun call swift#Run(0, ) 58 | 59 | " See |:SwiftEmitIr| for docs 60 | command! -nargs=* -buffer SwiftEmitIr call swift#Emit(0, "ir", 0, ) 61 | 62 | " See |:SwiftEmitSil| for docs 63 | command! -nargs=* -buffer -bang SwiftEmitSil call swift#Emit(0, "sil", 0, ) 64 | 65 | " See |:SwiftEmitAsm| for docs 66 | command! -nargs=* -buffer SwiftEmitAsm call swift#Emit(0, "assembly", 0, ) 67 | 68 | " See |:SwiftEmitObjcHeader| for docs 69 | command! -nargs=* -buffer SwiftEmitHeader call swift#Emit(0, "objc-header", 0, ) 70 | 71 | " See |:SwiftRunTests| for docs 72 | command! -nargs=* -buffer SwiftRunTests call swift#RunTests() 73 | 74 | " See |:SwiftVersion| for docs 75 | command! -buffer -bar SwiftVersion call swift#PrintVersion() 76 | 77 | " Tab command variants {{{2 78 | 79 | if has("windows") 80 | command! -nargs=* -buffer TabSwiftEmitIr call swift#Emit(1, "ir", 0, ) 81 | command! -nargs=* -buffer -bang TabSwiftEmitSil call swift#Emit(1, "sil", 0, ) 82 | command! -nargs=* -buffer TabSwiftEmitAsm call swift#Emit(1, "assembly", 0, ) 83 | command! -nargs=* -buffer TabSwiftEmitHeader call swift#Emit(1, "objc-header", 0, ) 84 | endif 85 | 86 | " Mappings {{{1 87 | 88 | " Map ⌘R in MacVim to :SwiftRun 89 | nnoremap :SwiftRun 90 | 91 | " Map ⌘⇧R in MacVim to :SwiftRun! pre-filled with the last args 92 | nnoremap :SwiftRun! =join(b:swift_last_swift_args)eswift#AppendCmdLine(' -- ' . join(b:swift_last_args)) 93 | 94 | if !exists("b:swift_last_swift_args") || !exists("b:swift_last_args") 95 | let b:swift_last_swift_args = [] 96 | let b:swift_last_args = [] 97 | endif 98 | 99 | " Miscellaneous {{{1 100 | 101 | " Add support to NERDCommenter 102 | if !exists('g:swift_setup_NERDCommenter') 103 | let g:swift_setup_NERDCommenter = 1 104 | 105 | let s:delimiter_map = { 'swift': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/' } } 106 | 107 | if exists('g:NERDDelimiterMap') 108 | call extend(g:NERDDelimiterMap, s:delimiter_map) 109 | elseif exists('g:NERDCustomDelimiters') 110 | call extend(g:NERDCustomDelimiters, s:delimiter_map) 111 | else 112 | let g:NERDCustomDelimiters = s:delimiter_map 113 | endif 114 | unlet s:delimiter_map 115 | endif 116 | 117 | " Check for 'showmatch' because it doesn't work right with \() 118 | if &showmatch && !get(g:, 'swift_suppress_showmatch_warning', 0) 119 | echohl WarningMsg 120 | echomsg "Swift string interpolations do not work well with 'showmatch'" 121 | echohl None 122 | echomsg "It is recommended that you turn it off and use matchparen instead" 123 | let g:swift_suppress_showmatch_warning = 1 124 | endif 125 | 126 | " Cleanup {{{1 127 | 128 | let b:undo_ftplugin = " 129 | \ setlocal expandtab< shiftwidth< tabstop< softtabstop< textwidth< 130 | \|setlocal colorcolumn< 131 | \|setlocal formatoptions< suffixesadd< comments< commentstring< 132 | \|setlocal showmatch< 133 | \|if exists('b:swift__did_set_fold') 134 | \|setlocal foldmethod< foldlevel< 135 | \|unlet b:swift__did_set_fold 136 | \|endif 137 | \|if exists('b:swift__did_set_conceallevel') 138 | \|setlocal conceallevel< 139 | \|unlet b:swift__did_set_conceallevel 140 | \|endif 141 | \|delcommand SwiftRun 142 | \|delcommand SwiftEmitIr 143 | \|delcommand SwiftEmitSil 144 | \|delcommand SwiftEmitAsm 145 | \|delcommand SwiftEmitHeader 146 | \|if has('windows') 147 | \|delcommand TabSwiftEmitIr 148 | \|delcommand TabSwiftEmitSil 149 | \|delcommand TabSwiftEmitAsm 150 | \|delcommand TabSwiftEmitHeader 151 | \|endif 152 | \|nunmap 153 | \|nunmap 154 | \|unlet! b:swift_last_args b:swift_last_swift_args 155 | \" 156 | 157 | " }}} 158 | 159 | let &cpo = s:save_cpo 160 | unlet s:save_cpo 161 | 162 | " vim: set et sw=4 ts=4: 163 | -------------------------------------------------------------------------------- /indent/swift.vim: -------------------------------------------------------------------------------- 1 | " File: swift.vim 2 | " Author: Kevin Ballard 3 | " Description: Indentation file for Swift 4 | " Last Modified: June 05, 2014 5 | 6 | if exists("b:did_indent") 7 | finish 8 | endif 9 | let b:did_indent = 1 10 | 11 | setl autoindent smartindent nocindent 12 | 13 | let b:undo_indent = " 14 | \ setlocal autoindent< smartindent< cindent< 15 | \" 16 | 17 | " vim: set et sw=4 ts=4: 18 | -------------------------------------------------------------------------------- /plugin/swift.vim: -------------------------------------------------------------------------------- 1 | " File: plugin/swift.vim 2 | " Author: Kevin Ballard 3 | " Description: Plugin for Swift 4 | " Last Change: Feb 16, 2015 5 | 6 | if exists("g:loaded_syntastic_swift_filetype") 7 | finish 8 | endif 9 | let g:loaded_syntastic_swift_filetype = 1 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | if exists("g:syntastic_extra_filetypes") 15 | let g:syntastic_extra_filetypes += ['swift'] 16 | else 17 | let g:syntastic_extra_filetypes = ['swift'] 18 | endif 19 | 20 | " Syntastic added a built-in Swift checker that's dangerous. 21 | " It actually runs the file under the swift JIT instead of merely compiling 22 | " it. 23 | " Let's disable it for our users by setting g:syntastic_swift_checkers if the 24 | " user hasn't already set it. 25 | if !exists('g:syntastic_swift_checkers') 26 | let g:syntastic_swift_checkers = ['swiftc'] 27 | endif 28 | 29 | let &cpo = s:save_cpo 30 | unlet s:save_cpo 31 | -------------------------------------------------------------------------------- /syntax/swift.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: Swift 3 | " Maintainer: Kevin Ballard 4 | " Last Change: Jul 25, 2014 5 | 6 | if exists("b:current_syntax") 7 | finish 8 | endif 9 | 10 | " Version Compatibility {{{1 11 | 12 | " \@123 703 || v:version == 603 && has("patch1088") 14 | function! s:lookbehind(count, type) 15 | return '\@' . a:count . '<' . a:type 16 | endfunction 17 | else 18 | function! s:lookbehind(count, type) 19 | return '\@<' . a:type 20 | endfunction 21 | endif 22 | 23 | " Settings {{{1 24 | 25 | " iskeyword defines word characters, which affects \< and \> 26 | " The default seems to be @,48-57,_,192-255 27 | " We want it to match anything from identifier-character 28 | " Unfortunately we can only match unicode values up to 0xFF, anything higher 29 | " is assumed to be contained. But it's better than nothing 30 | let &l:iskeyword = '@,48-57,_,' 31 | \ . '168,170,173,175,178-181,183-186,' 32 | \ . '188-190,192-214,216-246,248-255' 33 | let &l:isident = &l:iskeyword 34 | 35 | " Syntax definitions {{{1 36 | 37 | " NB: These clusters are expected to only contain items that are at the 38 | " toplevel. Furthermore, the following set of clusters should cover all 39 | " toplevel syntax items. 40 | 41 | " @swiftDefs are definitions that cannot occur inside closures/functions 42 | syn cluster swiftDefs contains=NONE 43 | " @swiftItems are things that cannot be found in an expression, but are 44 | " not @swiftDefs 45 | syn cluster swiftItems contains=NONE 46 | " @swiftExprs are all other toplevel syntax items 47 | syn cluster swiftExprs contains=NONE 48 | 49 | " In order to support :syn-include embedding, we can't use contains values 50 | " like contains=TOP,@swiftDefs. This is because the syntax embedding marks all 51 | " our syntax items as `contained`. Instead, use combinations of the clusters. 52 | 53 | " Define a few lists that we're going to need later 54 | " These are all regex snippets, with implied word boundaries 55 | let s:declarations = ['class', 'struct', 'enum', 'protocol', 'extension', 56 | \'let', 'var', 'func', 'subscript', 'init', 'deinit', 'operator'] 57 | let s:modifiers = ['final', 'lazy', 'optional', 'required', 'override', 58 | \'dynamic', 'prefix', 'infix', 'postfix', 'convenience', 'weak', 59 | \'unowned', 'mutating', 'nonmutating'] 60 | let s:modifiers_suffixed = ['unowned\_s*(safe)', 'unowned\_s*(unsafe)'] 61 | let s:accessControl = ['public', 'private', 'internal'] 62 | 63 | let s:declarations_re = '\<\%(init\>[?!]\|\%('.join(s:declarations, '\|').'\)\>\)' 64 | let s:modifiers_re = '\<\%('.join(map(s:modifiers, 'v:val."\\>"'), '\|') 65 | \.'\|'.join(s:modifiers_suffixed, '\|').'\)' 66 | let s:accessControl_re = '\<\%('.join(s:accessControl, '\|').'\)\>' 67 | " inclues an optional parenthesized suffix 68 | let s:accessControl2_re = s:accessControl_re.'\%(\_s*(\_[^)]*)\)\=' 69 | " includes (optionally-suffixed) access conrol 70 | " as well as occasional modifiers like class/static 71 | let s:modifiers2_re = '\%('.s:modifiers_re.'\|'.s:accessControl2_re.'\|\\|\\)' 72 | 73 | " Identifiers {{{2 74 | 75 | syn match swiftIdentifier /\<\i\+\>/ display transparent contains=NONE 76 | 77 | syn match swiftIdentifier /`\i\+`/ transparent contains=NONE 78 | 79 | syn cluster swiftExprs add=swiftIdentifier 80 | 81 | 82 | " Keywords {{{2 83 | 84 | " Declarations {{{3 85 | 86 | " Keywords have priority over other matches, so use syn-match for the few 87 | " keywords that we want to reuse in other matches. 88 | exe 'syn match swiftKeyword /'.s:declarations_re.'/' 89 | 90 | " Access control {{{3 91 | 92 | " Define the keywords once because they're keywords, and again for @swiftItems 93 | " to support the (set) modifier. 94 | 95 | exe 'syn keyword swiftKeyword' join(s:accessControl) 96 | 97 | exe 'syn keyword swiftAccessControl' join(s:accessControl) 'nextgroup=swiftAccessControlScope skipwhite skipempty' 98 | exe 'syn match swiftAccessControlScope /(\_s*set\_s*)\ze\%(\_s*'.s:modifiers2_re.'\)*\_s*\<\%(var\|subscript\)\>/ contained skipwhite skipempty' 99 | syn cluster swiftItems add=swiftAccessControl 100 | 101 | " Other keywords {{{3 102 | 103 | syn keyword swiftKeyword import static typealias 104 | syn keyword swiftKeyword break case continue default defer do else fallthrough for guard 105 | syn keyword swiftKeyword if in repeat return switch where while 106 | syn match swiftKeyword ,\[?!]\?, 107 | syn keyword swiftKeyword catch dynamicType is rethrows super self Self throw throws try 108 | syn keyword swiftKeyword __COLUMN__ __FILE__ __FUNCTION__ __LINE__ 109 | 110 | " Special types {{{3 111 | 112 | exe 'syn match swiftKeyword /\.'.s:lookbehind(1,'=').'\%(Type\|Protocol\)\>/ display' 113 | 114 | " }}}3 115 | 116 | syn cluster swiftExprs add=swiftKeyword 117 | 118 | " Built-in types {{{2 119 | " This is just the types that represent primitives or other commonly-used 120 | " types, not everything that exists in Swift. 121 | 122 | " Structs/Classes {{{3 123 | 124 | " Primitive types 125 | syn keyword swiftType Int Int8 Int16 Int32 Int64 Word IntMax 126 | syn keyword swiftType UInt UInt8 UInt16 UInt32 UInt64 UWord UIntMax 127 | syn keyword swiftType Double Float Float32 Float64 Float80 128 | syn keyword swiftType Bool Bit Void 129 | 130 | " Containers 131 | syn keyword swiftType Array Dictionary Set Slice 132 | syn keyword swiftType Optional ImplicitlyUnwrappedOptional 133 | syn keyword swiftType ContiguousArray 134 | syn keyword swiftType ManagedBuffer ManagedBufferPointer ManagedProtoBuffer 135 | syn keyword swiftType ArraySlice DictionaryLiteral 136 | syn keyword swiftType SetIndex DictionaryIndex 137 | 138 | " String-related types 139 | syn keyword swiftType String StaticString UTF8 UTF16 UTF32 UnicodeScalar Character 140 | 141 | " Ranges/intervals 142 | syn keyword swiftType Range ClosedInterval HalfOpenInterval 143 | syn keyword swiftType StrideTo StrideThrough 144 | 145 | " Pointers 146 | syn keyword swiftType UnsafePointer UnsafeMutablePointer 147 | syn keyword swiftType AutoreleasingUnsafeMutablePointer 148 | syn keyword swiftType COpaquePointer CFunctionPointer 149 | syn keyword swiftType UnsafeBufferPointer UnsafeMutableBufferPointer 150 | 151 | " Sequences/Collections/Generators 152 | syn keyword swiftType IndexingGenerator LazySequence 153 | syn keyword swiftType LazyForwardCollection LazyBidirectionalCollection LazyRandomAccessCollection 154 | syn keyword swiftType FilterCollectionView FilterSequenceView MapCollectionView MapSequenceView 155 | syn keyword swiftType BidirectionalReverseView RandomAccessReverseView 156 | syn keyword swiftType UnsafeBufferPointerGenerator 157 | syn keyword swiftType EmptyCollection EmptyGenerator 158 | syn keyword swiftType GeneratorOf SequenceOf GeneratorSequence 159 | syn keyword swiftType CollectionOfOne GeneratorOfOne 160 | syn keyword swiftType Zip2 Repeat PermutationGenerator 161 | syn keyword swiftType AnyBidirectionalCollection AnyBidirectionalIndex 162 | syn keyword swiftType AnyForwardCollection AnyForwardIndex 163 | syn keyword swiftType AnyRandomAccessCollection AnyRandomAccessIndex 164 | syn keyword swiftType AnySequence AnyGenerator IndexingGenerator 165 | syn keyword swiftType SinkOf 166 | 167 | " C compatibility 168 | syn keyword swiftType CInt CUnsignedInt CShort CUnsignedShort CLong CUnsignedLong CLongLong CUnsignedLongLong 169 | syn keyword swiftType \CChar CSignedChar CUnsignedChar CChar16 CChar32 CWideChar CBool 170 | syn keyword swiftType CDouble CFloat 171 | syn keyword swiftType CVarArgType CVaListPointer VaListBuilder 172 | 173 | " Miscellaneous 174 | syn keyword swiftType Unmanaged 175 | syn keyword swiftType ObjectIdentifier 176 | syn keyword swiftType FloatingPointClassification 177 | syn keyword swiftType MirrorDisposition QuickLookObject 178 | syn keyword swiftType UnicodeDecodingResult 179 | syn keyword swiftType RawRepresentable 180 | syn keyword swiftType NonObjectiveCBase 181 | syn keyword swiftType Selector 182 | syn keyword swiftType RawByte 183 | 184 | syn cluster swiftExprs add=swiftType 185 | 186 | " Protocols {{{3 187 | 188 | syn keyword swiftProtocol Any AnyObject AnyClass 189 | syn keyword swiftProtocol ForwardIndexType BidirectionalIndexType RandomAccessIndexType 190 | syn keyword swiftProtocol Comparable Hashable Equatable Strideable Reflectable Sliceable MutableSliceable 191 | syn keyword swiftProtocol NilLiteralConvertible DictionaryLiteralConvertible ArrayLiteralConvertible IntegerLiteralConvertible ExtendedGraphemeClusterLiteralConvertible CharacterLiteralConvertible FloatLiteralConvertible StringLiteralConvertible StringInterpolationConvertible BooleanLiteralConvertible 192 | syn keyword swiftProtocol Streamable Printable DebugPrintable 193 | syn keyword swiftProtocol UnicodeCodecType 194 | syn keyword swiftProtocol IntegerType SignedIntegerType UnsignedIntegerType BooleanType FloatingPointType 195 | syn keyword swiftProtocol SignedNumberType AbsoluteValuable IntervalType 196 | syn keyword swiftProtocol IntegerArithmeticType 197 | syn keyword swiftProtocol CollectionType MutableCollectionType SequenceType GeneratorType 198 | syn keyword swiftProtocol RawOptionSetType BitwiseOperationsType OptionSetType SetAlgebraType 199 | syn keyword swiftProtocol OutputStreamType SinkType 200 | syn keyword swiftProtocol ExtensibleCollectionType 201 | syn keyword swiftProtocol MirrorType 202 | syn keyword swiftProtocol StringElementType 203 | syn keyword swiftProtocol AnyCollectionType 204 | syn keyword swiftProtocol CustomDebugStringConvertible CustomStringConvertible 205 | syn keyword swiftProtocol CustomLeafReflectable CustomPlaygroundQuickLookable CustomReflectable 206 | syn keyword swiftProtocol ErrorType 207 | 208 | syn cluster swiftExprs add=swiftProtocol 209 | 210 | " Built-in functions {{{2 211 | 212 | let s:functions = [ 213 | \ 'abs', 'advance', 'alignof', 'alignofValue', 'assert', 'assertionFailure', 'contains', 'count', 214 | \ 'debugPrint', 'debugPrintln', 'distance', 'dropFirst', 'dropLast', 'dump', 'enumerate', 'equal', 'extend', 215 | \ 'fatalError', 'filter', 'find', 'first', 'getVaList', 'indices', 'insert', 'isEmpty', 216 | \ 'isUniquelyReferenced', 'isUniquelyReferencedNonObjC', 'join', 'last', 'lazy', 'lexicographicalCompare', 217 | \ 'map', 'max', 'maxElement', 'min', 'minElement', 'numericCast', 'overlaps', 'partition', 'precondition', 218 | \ 'preconditionFailure', 'prefix', 'print', 'println', 'reduce', 'reflect', 'removeAll', 'removeAtIndex', 219 | \ 'removeLast', 'removeRange', 'reverse', 'sizeof', 'sizeofValue', 'sort', 'sorted', 'splice', 'split', 220 | \ 'startsWith', 'stride', 'strideof', 'strideofValue', 'suffix', 'swap', 'toDebugString', 'toString', 221 | \ 'transcode', 'underestimateCount', 'unsafeAddressOf', 'unsafeBitCast', 'unsafeDowncast', 'unsafeUnwrap', 222 | \ 'withExtendedLifetime', 'withUnsafeMutablePointer', 'withUnsafeMutablePointers', 'withUnsafePointer', 223 | \ 'withUnsafePointers', 'withVaList', 'zip' 224 | \] 225 | let s:functions += ['anyGenerator', 'readLine'] " Swift 2 226 | let s:functions_re = '\<\%(\.'.s:lookbehind(1,'!').'\|\%(\.'.s:lookbehind(1,'!').'Swift\.\)'.s:lookbehind(6,'=').'\)\%('.join(s:functions, '\|').'\)\>\ze(' 227 | exe 'syn match swiftStdlibFunction /'.s:functions_re.'/ display' 228 | syn cluster swiftExprs add=swiftStdlibFunction 229 | 230 | " Literals {{{2 231 | 232 | syn cluster swiftLiteral contains=NONE 233 | syn cluster swiftExprs add=@swiftLiteral 234 | 235 | " Dec, Bin, Oct, Hex integer literals {{{3 236 | syn match swiftInteger display /\<\d[0-9_]*/ 237 | syn match swiftInteger display /\<0b[01][01_]*/ 238 | syn match swiftInteger display /\<0o\o[0-7_]*/ 239 | syn match swiftInteger display /\<0x\x[0-9a-fA-F_]*/ 240 | 241 | syn cluster swiftLiteral add=swiftInteger 242 | 243 | " Float and hex float literals {{{3 244 | " NB: Swift's documentation allows a decimal integer literal to also match a 245 | " float literal. We don't want that here. 246 | syn match swiftFloat display /\<\d[0-9_]*\.\d[0-9_]*\%([eE][-+]\?\d[0-9_]*\)\?\>/ 247 | syn match swiftFloat display /\<\d[0-9_]*\%(\.\d[0-9_]*\)\?[eE][-+]\?\d[0-9_]*\>/ 248 | syn match swiftFloat display /\<0x\x[0-9a-fA-F_]*\%(\.\x[0-9a-fA-F_]*\)\?[pP][-+]\?\d[0-9_]*\>/ 249 | 250 | syn cluster swiftLiteral add=swiftFloat 251 | 252 | " String literals {{{3 253 | 254 | syn region swiftString start=/"/ end=/"/ end=/$/ keepend oneline contains=swiftStringEscape,swiftStringEscapeError,swiftInterpolation,@Spell 255 | syn match swiftStringEscapeError display contained /\\./ 256 | syn match swiftStringEscape contained /\\[0\\tnr"']/ extend 257 | syn match swiftStringEscapeError display contained /\\\%(x\x\{,2}\|u\x\{,4}\|U\x\{,8}\)/ 258 | syn region swiftStringEscape matchgroup=swiftStringEscapeUnicode start="\\u{" end=/}\|\ze"/ display contained contains=swiftStringEscapeUnicodeError keepend 259 | exe 'syn region swiftStringEscapeUnicodeError start=/\_X\|{'.s:lookbehind(1,'=').'\x\{8}\zs\_[^}]/ end=/}/ display contained' 260 | 261 | syn region swiftInterpolation matchgroup=swiftInterpolationDelim start=/\\(/ end=/)/ contained oneline contains=@swiftDefs,@swiftItems,@swiftExprs 262 | 263 | syn cluster swiftLiteral add=swiftString 264 | 265 | " Boolean literals {{{3 266 | 267 | syn keyword swiftBoolean true false 268 | 269 | syn cluster swiftLiteral add=swiftBoolean 270 | 271 | " Nil literal {{{3 272 | 273 | syn keyword swiftNil nil 274 | 275 | syn cluster swiftLiteral add=swiftNil 276 | 277 | " Library values {{{2 278 | 279 | exe 'syn match swiftLibraryValue /\.'.s:lookbehind(1,'!').'\/' 280 | 281 | exe 'syn match swiftLibraryEnumValue /\.'.s:lookbehind(1,'=').'\%(Some\ze(\|None\>\)/' 282 | 283 | syn cluster swiftExprs add=swiftLibraryValue,swiftLibraryEnumValue 284 | 285 | " Miscellaneous {{{2 286 | 287 | syn match swiftOperator display ,\%(//\|/\*\)\@![-/=+!*%<>&|^~.]\+, transparent contains=NONE 288 | 289 | syn region swiftBalancedParens matchgroup=swiftBalancedParens start="(" end=")" transparent contains=@swiftExprs 290 | 291 | syn region swiftClosure matchgroup=swiftClosure start="{" end="}" contains=swiftClosureCaptureList,swiftClosureSimple fold 292 | syn region swiftClosureSimple start='[^}[:space:]]' end='\ze}' transparent contained contains=@swiftItems,@swiftExprs,swiftPlaceholder 293 | syn region swiftClosureCaptureList start="\[" end="\]" contained contains=@swiftItems,@swiftExprs,swiftClosureCaptureListOwnership nextgroup=swiftClosureSimple skipwhite skipempty 294 | syn match swiftClosureCaptureListOwnership /\<\%(strong\>\|weak\>\|unowned\%((safe)\|(unsafe)\|\>\)\)/ contained 295 | syn match swiftPlaceholder /\$\d\+/ contained 296 | 297 | syn match swiftAttribute /@\i\+/ nextgroup=swiftAttributeArguments skipwhite skipempty 298 | syn region swiftAttributeArguments matchgroup=swiftAttribute start="(" end=")" contains=@swiftExprs,swiftAttributeArgumentsNest contained 299 | syn region swiftAttributeArgumentsNest matchgroup=swiftAttributeArguments start="(" end=")" transparent contained 300 | syn region swiftAttributeArgumentsNest matchgroup=swiftAttributeArguments start="\[" end="\]" transparent contained 301 | syn region swiftAttributeArgumentsNest matchgroup=swiftAttributeArguments start="{" end="}" transparent contained 302 | 303 | syn cluster swiftExprs add=swiftOperator,swiftBalancedParens,swiftClosure,swiftAttribute 304 | 305 | " Declarations {{{2 306 | 307 | " Types (struct/class/etc) {{{3 308 | syn region swiftTypeDef start=/\<\%(class\|struct\|enum\|protocol\|extension\)\>/ end=/\ze{/ end=/\ze;/ contains=@swiftExprs,swiftGenerics nextgroup=swiftTypeBody keepend 309 | syn region swiftTypeBody matchgroup=swiftTypeBody start="{" end="}" contained contains=@swiftDefs,@swiftItems,@swiftExprs fold 310 | syn cluster swiftDefs add=swiftTypeDef 311 | 312 | " Operators {{{3 313 | syn match swiftOperatorDef /\\_s*[^[:space:]();<]\+\_s*\ze\%((\|<\)/ contains=@swiftExprs nextgroup=swiftFuncArgs,swiftFuncGenerics 325 | syn match swiftSpecialFuncDef /\<\%(init\>[?!]\?\|deinit\>\)\_s*\ze(/ contains=swiftKeyword nextgroup=swiftFuncArgs 326 | syn region swiftFuncGenerics start="<" end="\ze\_." contained contains=swiftGenerics nextgroup=swiftFuncArgs skipwhite skipempty 327 | syn region swiftFuncArgs matchgroup=swiftFuncArgs start="(" end=")" contained contains=@swiftExprs,swiftFuncArgInout transparent nextgroup=swiftFuncBody skipwhite skipempty 328 | syn region swiftFuncBody matchgroup=swiftFuncBody start="{" end="}" contained contains=@swiftItems,@swiftExprs fold 329 | syn keyword swiftFuncArgInout contained inout 330 | syn cluster swiftItems add=swiftFuncDef 331 | syn cluster swiftDefs add=swiftSpecialFuncDef 332 | 333 | " Subscripts {{{3 334 | 335 | syn match swiftSubscriptDef /\\_[^{]*\ze{/ contains=@swiftExprs nextgroup=swiftSubscriptBody 336 | syn region swiftSubscriptBody matchgroup=swiftSubscriptBody start="{" end="}" fold contained contains=@swiftItems,@swiftExprs,swiftSubscriptAttribute 337 | syn keyword swiftSubscriptAttribute contained nextgroup=swiftSubscriptAttriuteBlock skipwhite skipempty get 338 | syn match swiftSubscriptAttribute /\/ contained nextgroup=swiftSubscriptAttributeArg,swiftSubscriptAttriuteBlock skipwhite skipempty 339 | syn match swiftSubscriptAttribute /\<\%(mutating\|nonmutating\)\>\ze\_s*\<\%(get\|set\)\>/ contained nextgroup=swiftSubscriptAttribute skipwhite skipempty 340 | syn region swiftSubscriptAttributeArg matchgroup=swiftSubscriptAttributeArg start="(" end=")" contained contains=@swiftExprs nextgroup=swiftSubscriptAttributeBlock skipwhite skipempty 341 | syn region swiftSubscriptAttributeBlock matchgroup=swiftSubscriptAttributeBlock start="{" end="}" contained contains=@swiftItems,@swiftExprs fold 342 | syn cluster swiftDefs add=swiftSubscriptDef 343 | 344 | " Variables {{{3 345 | 346 | syn match swiftVarDef /\\_s*\%([^[:space:][:punct:][:cntrl:][:digit:]]\|\i\)\%([^[:space:][:punct:][:cntrl:]]\|\i\)*/ contains=swiftKeyword,swiftIdentifier nextgroup=swiftVarTypeAscription,swiftVarDefaultValue,swiftVarBody skipwhite skipempty 347 | syn match swiftVarTypeAscription /:/ contained nextgroup=swiftVarType skipwhite skipempty 348 | syn region swiftVarType start=/./ end=/\ze\_./ contained contains=swiftTypeExpr nextgroup=swiftVarDefaultValue,swiftVarBody skipwhite skipempty 349 | syn match swiftVarDefaultValue /=/ contained nextgroup=swiftVarDefaultValueExpr skipwhite skipempty 350 | syn region swiftVarDefaultValueExpr start=/\S/ end=/\ze\_./ contained contains=@swiftExprs nextgroup=swiftVarBody skipwhite skipempty 351 | syn region swiftVarBody matchgroup=swiftVarBody start="{" end="}" fold contained contains=@swiftItems,@swiftExprs,swiftVarAttribute 352 | syn keyword swiftVarAttribute contained nextgroup=swiftVarAttributeBlock skipwhite skipempty get 353 | syn match swiftVarAttribute /\<\%(set\|willSet\|didSet\)\>/ contained nextgroup=swiftVarAttributeArg,swiftVarAttributeBlock skipwhite skipempty 354 | syn match swiftVarAttribute /\<\%(mutating\|nonmutating\)\>\ze\_s*\<\%(get\|set\|willSet\|didSet\)\>/ contained nextgroup=swiftVarAttribute skipwhite skipempty 355 | syn region swiftVarAttributeArg matchgroup=swiftVarAttributeArg start="(" end=")" contained contains=@swiftExprs nextgroup=swiftVarAttributeBlock skipwhite skipempty 356 | syn region swiftVarAttributeBlock matchgroup=swiftVarAttributeBlock start="{" end="}" contained contains=@swiftItems,@swiftExprs fold 357 | syn cluster swiftItems add=swiftVarDef 358 | 359 | " Type patterns {{{3 360 | 361 | syn region swiftTypeExpr start=/./ end=/\ze\_[[:space:]{})\]]/ contained contains=@swiftExprs,swiftTypeArrayDict,swiftGenerics skipwhite skipempty 362 | syn region swiftTypeArrayDict matchgroup=swiftTypeBrackets start='\[' end='\]' contained contains=@swiftExprs,swiftTypeArrayDict,swiftTypeBracketsColon keepend extend 363 | syn match swiftTypeBracketsColon /:/ contained 364 | syn region swiftGenerics matchgroup=swiftGenerics start=// contained contains=swiftKeyword,swiftType,swiftProtocol,@swiftLiteral,swiftIdentifier,swiftBalancedParens,swiftTypeArrayDict,swiftGenerics,swiftGenericsEqual keepend extend 365 | syn match swiftGenericsEqual /==/ contained transparent contains=NONE 366 | 367 | " Modifiers {{{3 368 | 369 | exe 'syn match swiftDeclarationModifier /'.s:modifiers_re.'\ze\%(\_s*'.s:modifiers2_re.'\)*\_s*'.s:declarations_re.'/' 370 | exe 'syn match swiftDeclarationModifier /\<\%(class\|static\)\>\ze\%(\_s*\w\+\%(\_s*(\_s*\w*\_s*)\)\=\)\{,}\_s*'.s:declarations_re.'/' 371 | syn cluster swiftItems add=swiftDeclarationModifier 372 | 373 | " Availability Condition {{{3 374 | 375 | syn match swiftAvailabilityCondition /#available\>/ nextgroup=swiftAvailabilityArguments skipwhite 376 | syn region swiftAvailabilityArguments matchgroup=swiftAvailabilityCondition start="(" end=")" contained contains=swiftAvailabilityPlatformName 377 | syn keyword swiftAvailabilityPlatformName OSX iOS watchOS iOSApplicationExtension OSXApplicationExtension contained nextgroup=swiftAvailabilityPlatformVersion skipwhite 378 | syn match swiftAvailabilityPlatformName /\*/ contained 379 | syn match swiftAvailabilityPlatformVersion /[0-9]\+\%(\.[0-9]\+\)\{,2}/ contained 380 | 381 | syn cluster swiftExprs add=swiftAvailabilityCondition 382 | 383 | " Comments {{{2 384 | 385 | syn region swiftCommentLine excludenl start="//" end="$" contains=@swiftCommentLineMarker,@Spell oneline 386 | syn region swiftCommentBlock matchgroup=swiftCommentBlockDelim start="/\*" end="\*/" contains=swiftCommentBlockNest,@swiftCommentBlockMarker,@Spell keepend 387 | syn region swiftCommentBlockNest matchgroup=swiftCommentBlockDelim start="/\*" end="\*/" contains=swiftCommentBlockNest,@swiftCommentBlockMarker,@Spell contained keepend extend 388 | 389 | syn region swiftDocCommentLine excludenl start="///" end="$" contains=@swiftCommentLineMarker,@Spell oneline 390 | syn region swiftDocCommentBlock matchgroup=swiftDocCommentBlockDelim start="/\*\*" end="\*/" contains=swiftCommentBlockNest,@swiftCommentBlockMarker,@Spell keepend 391 | 392 | " it seems the markers don't care about word boundaries, only that the literal 393 | " substring matches 394 | syn match swiftCommentTodo /TODO:\|FIXME:/ contained 395 | " for MARK: we want to highlight the rest of the line as well. TODO: and 396 | " FIXME: actually use the rest of the line too, but marks are used for 397 | " separation and should be more distinct 398 | syn region swiftCommentLineMark excludenl start=/MARK:/ end=/$/ contained contains=@Spell oneline 399 | syn cluster swiftCommentLineMarker contains=swiftCommentTodo,swiftCommentLineMark 400 | syn region swiftCommentBlockMark excludenl start=/MARK:/ end=/$/ end=,\ze/\*, contained contains=@Spell oneline 401 | syn cluster swiftCommentBlockMarker contains=swiftCommentTodo,swiftCommentBlockMark 402 | 403 | syn cluster swiftExprs add=swiftCommentLine,swiftCommentBlock,swiftDocCommentLine,swiftDocCommentBlock 404 | 405 | " Conditional Compilation {{{2 406 | 407 | syn region swiftConditionalCompilation excludenl start=/^\s*#if\>/ end=/$/ contains=swiftBuildConfiguration oneline 408 | syn region swiftConditionalCompilation excludenl start=/^\s*#else\>/ end=/$/ oneline 409 | syn region swiftConditionalCompilation excludenl start=/^\s*#elseif\>/ end=/$/ contains=swiftBuildConfiguration oneline 410 | syn region swiftConditionalCompilation excludenl start=/^\s*#endif\>/ end=/$/ oneline 411 | 412 | syn match swiftBuildConfiguration /\/ contained contains=swiftBoolean 415 | 416 | syn keyword swiftBuildConfigurationOS OSX iOS watchOS contained 417 | syn keyword swiftBuildConfigurationArch x86_64 arm arm64 i386 contained 418 | 419 | syn cluster swiftExprs add=swiftConditionalCompilation 420 | 421 | " Shebang {{{2 422 | 423 | syn region swiftShebang excludenl start=/^\%1l#!/ end=/$/ oneline 424 | 425 | " Default highlighting {{{1 426 | 427 | hi def link swiftKeyword Keyword 428 | hi def link swiftType Type 429 | hi def link swiftProtocol PreProc 430 | 431 | hi def link swiftAccessControl Keyword 432 | hi def link swiftAccessControlScope swiftAccessControl 433 | 434 | hi def link swiftStdlibFunction Function 435 | 436 | hi def link swiftLiteral Number 437 | hi def link swiftInteger swiftLiteral 438 | hi def link swiftFloat swiftLiteral 439 | hi def link swiftBoolean swiftLiteral 440 | hi def link swiftNil swiftKeyword 441 | 442 | hi def link swiftLibraryValue Identifier 443 | hi def link swiftLibraryEnumValue swiftLibraryValue 444 | 445 | hi def link swiftString String 446 | hi def link swiftStringEscapeError Error 447 | hi def link swiftStringEscape Special 448 | hi def link swiftStringEscapeUnicode swiftStringEscape 449 | hi def link swiftStringEscapeUnicodeError swiftStringEscapeError 450 | hi def link swiftInterpolationDelim Delimiter 451 | 452 | hi def link swiftClosureCaptureListOwnership swiftKeyword 453 | hi def link swiftPlaceholder Identifier 454 | 455 | hi def link swiftAttribute Macro 456 | 457 | hi def link swiftOperatorDefKeywords swiftKeyword 458 | hi def link swiftOperatorPrecedence swiftKeyword 459 | hi def link swiftOperatorPrecedenceLevel swiftInteger 460 | hi def link swiftOperatorAssociativity swiftKeyword 461 | hi def link swiftOperatorAssociativityValue swiftKeyword 462 | hi def link swiftOperatorAssignment swiftKeyword 463 | 464 | hi def link swiftFuncArgInout swiftKeyword 465 | 466 | hi def link swiftSubscriptAttribute swiftKeyword 467 | hi def link swiftVarAttribute swiftKeyword 468 | 469 | hi def link swiftDeclarationModifier swiftKeyword 470 | 471 | hi def link swiftAvailabilityCondition Macro 472 | hi def link swiftAvailabilityPlatformName Special 473 | hi def link swiftAvailabilityPlatformVersion Number 474 | 475 | hi def link swiftCommentLine Comment 476 | hi def link swiftCommentBlock swiftCommentLine 477 | hi def link swiftCommentBlockDelim swiftCommentBlock 478 | hi def link swiftCommentBlockNest swiftCommentBlock 479 | 480 | hi def link swiftDocCommentLine SpecialComment 481 | hi def link swiftDocCommentBlock swiftDocCommentLine 482 | hi def link swiftDocCommentBlockDelim swiftDocCommentBlock 483 | 484 | hi def link swiftCommentTodo Todo 485 | hi def link swiftCommentLineMark PreProc 486 | hi def link swiftCommentBlockMark PreProc 487 | 488 | hi def link swiftConditionalCompilation PreProc 489 | hi def link swiftBuildConfiguration swiftConditionalCompilation 490 | hi def link swiftBuildConfigurationOS Special 491 | hi def link swiftBuildConfigurationArch Special 492 | 493 | hi def link swiftShebang swiftCommentLine 494 | 495 | " }}}1 496 | 497 | syn sync minlines=200 498 | syn sync maxlines=500 499 | 500 | let b:current_syntax = "swift" 501 | 502 | " vim: set et sw=4 ts=4: 503 | -------------------------------------------------------------------------------- /syntax_checkers/swift/swiftc.vim: -------------------------------------------------------------------------------- 1 | " File: syntax_checkers/swift/swiftc.vim 2 | " Author: Kevin Ballard 3 | " Description: Syntastic checker for Swift 4 | " Last Change: Jul 12, 2015 5 | 6 | if exists("g:loaded_syntastic_swift_swiftc_checker") 7 | finish 8 | endif 9 | let g:loaded_syntastic_swift_swiftc_checker = 1 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | function! SyntaxCheckers_swift_swiftc_IsAvailable() dict 15 | let exec = self.getExec() 16 | if exec ==? 'swiftc' 17 | call system(swift#xcrun('-find', 'swiftc')) 18 | return v:shell_error == 0 19 | endif 20 | return executable(exec) 21 | endfunction 22 | 23 | function! SyntaxCheckers_swift_swiftc_GetLocList() dict 24 | let platformInfo = swift#platform#getPlatformInfo(swift#platform#detect(), 1) 25 | if empty(platformInfo) 26 | return [] 27 | endif 28 | let args = swift#platform#argsForPlatformInfo(platformInfo) 29 | 30 | let exec = self.getExec() 31 | if exec ==? 'swiftc' 32 | let exe = swift#xcrun('swiftc') 33 | else 34 | let exe = syntastic#util#shescape(exec) 35 | endif 36 | 37 | let makeprg = self.makeprgBuild({ 38 | \ 'exe': exe, 39 | \ 'args_before': args, 40 | \ 'args_after': '-parse'}) 41 | 42 | let errorformat = 43 | \ '%E%f:%l:%c: error: %m,' . 44 | \ '%W%f:%l:%c: warning: %m,' . 45 | \ '%Z%\s%#^~%#,' . 46 | \ '%-G%.%#' 47 | 48 | return SyntasticMake({ 49 | \ 'makeprg': makeprg, 50 | \ 'errorformat': errorformat }) 51 | endfunction 52 | 53 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 54 | \ 'filetype': 'swift', 55 | \ 'name': 'swiftc'}) 56 | 57 | let &cpo = s:save_cpo 58 | unlet s:save_cpo 59 | --------------------------------------------------------------------------------