1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 06:40:05 +08:00
SpaceVim/bundle/django-plus.vim/autoload/djangoplus/detect.vim
2022-05-07 08:03:49 +08:00

222 lines
5.2 KiB
VimL

" 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