mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 06:40:05 +08:00
222 lines
5.2 KiB
VimL
Vendored
222 lines
5.2 KiB
VimL
Vendored
" Django is detected by looking for clues of a Django project. Directories
|
|
" have been traversed are cached to speed up subsequent scans.
|
|
let s:seen = {}
|
|
let s:django_app_modules = [
|
|
\ 'admin',
|
|
\ 'apps',
|
|
\ 'managers',
|
|
\ 'migrations',
|
|
\ 'models',
|
|
\ 'templatetags',
|
|
\ 'tests',
|
|
\ 'urls',
|
|
\ 'views',
|
|
\ ]
|
|
|
|
let s:django_app_dirs = [
|
|
\ 'static',
|
|
\ 'templates',
|
|
\ ]
|
|
|
|
let s:pathsep = expand('/')
|
|
let s:pathsep_p = escape(s:pathsep, '\')
|
|
|
|
|
|
" Test a file name to see if it's a python module.
|
|
function! s:has_module(dirname, module)
|
|
return filereadable(a:dirname.'/'.a:module.'.py')
|
|
\ || filereadable(a:dirname.'/'.a:module.'/__init__.py')
|
|
endfunction
|
|
|
|
|
|
" Test a directory for a management script>
|
|
function! s:is_django_project(dirname)
|
|
if filereadable(a:dirname.'/manage.py')
|
|
let $_DJANGOPLUS_MANAGEMENT = a:dirname.'/manage.py'
|
|
return 1
|
|
endif
|
|
return 0
|
|
endfunction
|
|
|
|
|
|
function! s:settings_path() abort
|
|
if exists('s:django_conf_path')
|
|
return s:django_conf_path
|
|
endif
|
|
|
|
if !exists('$_DJANGOPLUS_MANAGEMENT') || !filereadable($_DJANGOPLUS_MANAGEMENT)
|
|
return ''
|
|
endif
|
|
|
|
for line in readfile($_DJANGOPLUS_MANAGEMENT)
|
|
let module = matchstr(line,
|
|
\ '\(["'']\)DJANGO_SETTINGS_MODULE\1,'
|
|
\.'\s*\(["'']\)\zs\%(\2\@!.\)\+\ze\2')
|
|
|
|
if !empty(module)
|
|
if module =~# '\.'
|
|
let module_path = join(split(module, '\.'), s:pathsep)
|
|
else
|
|
let module_path = module
|
|
endif
|
|
|
|
let module_path = fnamemodify($_DJANGOPLUS_MANAGEMENT, ':h')
|
|
\.s:pathsep.module_path
|
|
let conf_path = ''
|
|
|
|
if filereadable(module_path.'.py')
|
|
let conf_path = fnamemodify(module_path, ':h')
|
|
elseif filereadable(module_path.'/__init__.py')
|
|
let conf_path = module_path
|
|
endif
|
|
|
|
if !empty(conf_path)
|
|
let s:django_conf_path = conf_path
|
|
return s:django_conf_path
|
|
endif
|
|
endif
|
|
endfor
|
|
|
|
return ''
|
|
endfunction
|
|
|
|
|
|
function! s:is_django_settings(filename) abort
|
|
let settings_path = s:settings_path()
|
|
if empty(settings_path)
|
|
return 0
|
|
endif
|
|
|
|
return a:filename =~# '^'.settings_path.s:pathsep_p
|
|
endfunction
|
|
|
|
|
|
" Test a directory to see if it looks like a Django app.
|
|
function! s:is_django_app(dirname)
|
|
let min_matches = 2
|
|
let dirname = a:dirname
|
|
|
|
if filereadable(dirname.'/__init__.py')
|
|
" Apps are modules
|
|
let match_count = 0
|
|
for name in s:django_app_dirs
|
|
if isdirectory(dirname.'/'.name)
|
|
let match_count += 1
|
|
if match_count >= min_matches
|
|
return 1
|
|
endif
|
|
endif
|
|
endfor
|
|
|
|
for name in s:django_app_modules
|
|
if s:has_module(dirname, name)
|
|
let match_count += 1
|
|
if match_count >= match_count
|
|
return 1
|
|
endif
|
|
endif
|
|
endfor
|
|
endif
|
|
|
|
return 0
|
|
endfunction
|
|
|
|
|
|
" Scan parents for a match
|
|
function! s:scan(filename, func) abort
|
|
if empty(a:filename)
|
|
return 0
|
|
endif
|
|
|
|
let dirname = fnamemodify(a:filename, ':p:h')
|
|
let last_dir = ''
|
|
let depth = 0
|
|
let max_depth = get(g:, 'django_max_scan_depth', 10)
|
|
|
|
while depth < max_depth && dirname != last_dir && dirname !~ '^\/*$'
|
|
let last_dir = dirname
|
|
|
|
if has_key(s:seen, dirname)
|
|
if s:seen[dirname]
|
|
return 1
|
|
else
|
|
let dirname = fnamemodify(dirname, ':h')
|
|
continue
|
|
endif
|
|
endif
|
|
|
|
if call(a:func, [dirname])
|
|
let s:seen[dirname] = 1
|
|
return 1
|
|
endif
|
|
|
|
let s:seen[dirname] = 0
|
|
let depth += 1
|
|
let dirname = fnamemodify(dirname, ':h')
|
|
endwhile
|
|
|
|
return 0
|
|
endfunction
|
|
|
|
|
|
" Perform a quick check to see if the the current directory is a Django
|
|
" project. Returns 0 or 1 if the current directory is a Django project, and
|
|
" -1 if it's not.
|
|
function! s:simple_django_project(filename)
|
|
let cwd = getcwd()
|
|
if !has_key(s:seen, cwd)
|
|
let s:seen[cwd] = s:is_django_project(cwd)
|
|
endif
|
|
|
|
return s:seen[cwd] ? a:filename =~# '^'.escape(cwd, '.\^$[]').s:pathsep_p : -1
|
|
endfunction
|
|
|
|
|
|
" Detect Django related files
|
|
function! djangoplus#detect#filetype(filename) abort
|
|
if empty(a:filename)
|
|
return
|
|
endif
|
|
|
|
let is_django = s:simple_django_project(a:filename)
|
|
if is_django == -1
|
|
" Since the current directory isn't a Django project, perform a more
|
|
" exhaustive scan.
|
|
let is_django = s:scan(a:filename, 's:is_django_project')
|
|
\ || s:scan(a:filename, 's:is_django_app')
|
|
endif
|
|
|
|
if is_django
|
|
let b:is_django = 1
|
|
let filedir = fnamemodify(a:filename, ':h')
|
|
|
|
autocmd! CursorHold <buffer> call djangoplus#clear_template_cache()
|
|
|
|
if a:filename =~? '\.html\?$'
|
|
setfiletype htmldjango
|
|
elseif s:is_django_settings(a:filename)
|
|
setfiletype python
|
|
let b:is_django_settings = 1
|
|
elseif a:filename =~# '\.py$'
|
|
setfiletype python
|
|
else
|
|
for pat in get(g:, 'django_filetypes', [])
|
|
if a:filename =~# glob2regpat(pat)
|
|
let bft = &l:filetype
|
|
if !empty(bft)
|
|
let bft .= '.django'
|
|
else
|
|
let bft = 'django'
|
|
endif
|
|
execute 'setfiletype' bft
|
|
endif
|
|
endfor
|
|
|
|
for ft in split(&l:filetype, '\.')
|
|
execute 'runtime! ftplugin/'.ft.'.vim'
|
|
execute 'runtime! after/ftplugin/'.ft.'.vim'
|
|
endfor
|
|
endif
|
|
endif
|
|
endfunction
|