summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2017-02-13 10:36:38 +0000
committerw0rp <devw0rp@gmail.com>2017-02-13 10:36:38 +0000
commit5cdd1498b459403c7e54a4dd45f2f14b97969544 (patch)
treec93e54b0dbbd539428ff383474b8344544582bbd
parent3aa1d57b5715b18f1544d36a3101ff45a6a86239 (diff)
downloadale-5cdd1498b459403c7e54a4dd45f2f14b97969544.zip
#283 Fix linting buffers with no filename, by creating a filename with a guess for the file extension
-rw-r--r--autoload/ale/engine.vim12
-rw-r--r--autoload/ale/filetypes.vim60
-rw-r--r--test/test_filetype_mapping.vader29
3 files changed, 98 insertions, 3 deletions
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index fc6a7309..ed7b933a 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -286,11 +286,17 @@ function! ale#engine#EscapeCommandPart(command_part) abort
endfunction
function! s:TemporaryFilename(buffer) abort
+ let l:filename = fnamemodify(bufname(a:buffer), ':t')
+
+ if empty(l:filename)
+ " If the buffer's filename is empty, create a dummy filename.
+ let l:ft = getbufvar(a:buffer, '&filetype')
+ let l:filename = 'file' . ale#filetypes#GuessExtension(l:ft)
+ endif
+
" Create a temporary filename, <temp_dir>/<original_basename>
" The file itself will not be created by this function.
- return tempname()
- \ . (has('win32') ? '\' : '/')
- \ . fnamemodify(bufname(a:buffer), ':t')
+ return tempname() . (has('win32') ? '\' : '/') . l:filename
endfunction
" Given a command string, replace every...
diff --git a/autoload/ale/filetypes.vim b/autoload/ale/filetypes.vim
new file mode 100644
index 00000000..6174aa0e
--- /dev/null
+++ b/autoload/ale/filetypes.vim
@@ -0,0 +1,60 @@
+" Author: w0rp <devw0rp@gmail.com>
+" Description: This file handles guessing file extensions for filetypes, etc.
+
+function! ale#filetypes#LoadExtensionMap() abort
+ " Output includes:
+ " '*.erl setf erlang'
+ redir => l:output
+ silent exec 'autocmd'
+ redir end
+
+ let l:map = {}
+
+ for l:line in split(l:output, "\n")
+ " Parse filetypes, like so:
+ "
+ " *.erl setf erlang
+ " *.md set filetype=markdown
+ " *.snippet setlocal filetype=snippets
+ let l:match = matchlist(l:line, '\v^ *\*(\.[^ ]+).*set(f *| *filetype=|local *filetype=)([^ ]+)')
+
+ if !empty(l:match)
+ let l:map[substitute(l:match[3], '^=', '', '')] = l:match[1]
+ endif
+ endfor
+
+ return l:map
+endfunction
+
+let s:cached_map = {}
+
+function! s:GetCachedExtensionMap() abort
+ if empty(s:cached_map)
+ let s:cached_map = ale#filetypes#LoadExtensionMap()
+ endif
+
+ return s:cached_map
+endfunction
+
+function! ale#filetypes#GuessExtension(filetype) abort
+ let l:map = s:GetCachedExtensionMap()
+ let l:ext = get(l:map, a:filetype, '')
+
+ " If we have an exact match, like something for javascript.jsx, use that.
+ if !empty(l:ext)
+ return l:ext
+ endif
+
+ " If we don't have an exact match, use the first filetype in the compound
+ " filetype.
+ for l:part in split(a:filetype, '\.')
+ let l:ext = get(l:map, l:part, '')
+
+ if !empty(l:ext)
+ return l:ext
+ endif
+ endfor
+
+ " Return an empty string if we don't find anything.
+ return ''
+endfunction
diff --git a/test/test_filetype_mapping.vader b/test/test_filetype_mapping.vader
new file mode 100644
index 00000000..2d72491d
--- /dev/null
+++ b/test/test_filetype_mapping.vader
@@ -0,0 +1,29 @@
+Before:
+ augroup TestFiletypeGroup
+ autocmd!
+ autocmd BufEnter,BufRead *.x setf xfiletype
+ autocmd BufEnter,BufRead *.y set filetype=yfiletype
+ autocmd BufEnter,BufRead *.z setlocal filetype=zfiletype
+ autocmd BufEnter,BufRead *.jsx set filetype=javascript.jsx
+ augroup END
+
+After:
+ unlet! g:map
+ augroup TestFiletypeGroup
+ autocmd!
+ augroup END
+ augroup! TestFiletypeGroup
+
+Execute(ALE should parse autocmd filetypes correctly):
+ let g:map = ale#filetypes#LoadExtensionMap()
+
+ AssertEqual '.x', g:map['xfiletype']
+ AssertEqual '.y', g:map['yfiletype']
+ AssertEqual '.z', g:map['zfiletype']
+ AssertEqual '.jsx', g:map['javascript.jsx']
+
+Execute(ALE should guess file extensions appropriately):
+ " The whole string should be used, if there's a match.
+ AssertEqual '.jsx', ale#filetypes#GuessExtension('javascript.jsx')
+ " The first part should be used.
+ AssertEqual '.x', ale#filetypes#GuessExtension('xfiletype.yfiletype')