mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 09:20:06 +08:00
160 lines
5.4 KiB
Python
160 lines
5.4 KiB
Python
# ============================================================================
|
|
# FILE: defx.py
|
|
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
|
# License: MIT license
|
|
# ============================================================================
|
|
|
|
import typing
|
|
|
|
from defx.base.source import Base as Source
|
|
from defx.source.file.list import Source as SourceList
|
|
from defx.source.file import Source as SourceFile
|
|
from defx.context import Context
|
|
from defx.sort import sort
|
|
from defx.util import Nvim
|
|
from defx.util import cd, error
|
|
from pathlib import Path
|
|
|
|
|
|
Candidate = typing.Dict[str, typing.Any]
|
|
|
|
|
|
class Defx(object):
|
|
|
|
def __init__(self, vim: Nvim, context: Context,
|
|
source_name: str, cwd: str, index: int) -> None:
|
|
self._vim = vim
|
|
self._context = context
|
|
self._cwd = self._vim.call('getcwd')
|
|
self.cd(cwd)
|
|
|
|
self._source: Source = (SourceList(self._vim)
|
|
if source_name == 'file/list'
|
|
else SourceFile(self._vim))
|
|
self._index = index
|
|
self._enabled_ignored_files = not context.show_ignored_files
|
|
self._filtered_files = context.filtered_files.split(',')
|
|
self._ignored_files = context.ignored_files.split(',')
|
|
self._cursor_history: typing.Dict[str, Path] = {}
|
|
self._sort_method: str = self._context.sort
|
|
self._mtime: int = -1
|
|
self._opened_candidates: typing.Set[str] = set()
|
|
self._selected_candidates: typing.Set[str] = set()
|
|
self._nested_candidates: typing.Set[str] = set()
|
|
|
|
self._init_source()
|
|
|
|
def _init_source(self) -> None:
|
|
custom = self._vim.call('defx#custom#_get')['source']
|
|
name = self._source.name
|
|
if name in custom:
|
|
self._source.vars.update(custom[name])
|
|
|
|
def debug(self, expr: typing.Any) -> None:
|
|
error(self._vim, expr)
|
|
|
|
def cd(self, path: str) -> None:
|
|
self._cwd = str(Path(self._cwd).joinpath(path))
|
|
|
|
if self._context.auto_cd and Path(path).is_dir():
|
|
cd(self._vim, path)
|
|
|
|
def get_root_candidate(self) -> Candidate:
|
|
"""
|
|
Returns root candidate
|
|
"""
|
|
if not self._source:
|
|
return {}
|
|
|
|
root = self._source.get_root_candidate(self._context, Path(self._cwd))
|
|
root['is_root'] = True
|
|
root['is_opened_tree'] = False
|
|
root['is_selected'] = False
|
|
root['level'] = 0
|
|
root['root_marker'] = self._context.root_marker + (
|
|
self._source.name + ':' if self._source.name != 'file' else '')
|
|
root['word'] = root['root_marker'] + root['word']
|
|
|
|
return root
|
|
|
|
def tree_candidates(
|
|
self, path: str, base_level: int, max_level: int
|
|
) -> typing.List[Candidate]:
|
|
gathered_candidates = self.gather_candidates_recursive(
|
|
path, base_level, max_level)
|
|
|
|
if not self._opened_candidates and not self._nested_candidates:
|
|
return gathered_candidates
|
|
|
|
candidates = []
|
|
for candidate in gathered_candidates:
|
|
candidates.append(candidate)
|
|
candidate['level'] = base_level
|
|
candidate_path = str(candidate['action__path'])
|
|
|
|
if not candidate['is_directory']:
|
|
continue
|
|
if (candidate_path not in self._opened_candidates and
|
|
candidate_path not in self._nested_candidates):
|
|
continue
|
|
|
|
children = self.tree_candidates(
|
|
candidate_path, base_level + 1, max_level)
|
|
|
|
candidate['is_opened_tree'] = True
|
|
candidates += children
|
|
return candidates
|
|
|
|
def gather_candidates_recursive(
|
|
self, path: str, base_level: int, max_level: int
|
|
) -> typing.List[Candidate]:
|
|
|
|
candidates = self._gather_candidates(path, base_level)
|
|
if base_level >= max_level:
|
|
return candidates
|
|
|
|
ret = []
|
|
for candidate in candidates:
|
|
ret.append(candidate)
|
|
if candidate['is_directory']:
|
|
candidate['is_opened_tree'] = True
|
|
ret += self.gather_candidates_recursive(
|
|
str(candidate['action__path']), base_level + 1, max_level)
|
|
return ret
|
|
|
|
def _gather_candidates(
|
|
self, path: str, base_level: int = 0) -> typing.List[Candidate]:
|
|
"""
|
|
Returns file candidates
|
|
"""
|
|
if not self._source:
|
|
return []
|
|
|
|
candidates = self._source.gather_candidates(
|
|
self._context, Path(path))
|
|
|
|
if self._filtered_files != ['']:
|
|
new_candidates = []
|
|
for candidate in candidates:
|
|
matched = False
|
|
for glob in self._filtered_files:
|
|
if candidate['action__path'].match(glob):
|
|
matched = True
|
|
break
|
|
if matched or candidate['is_directory']:
|
|
new_candidates.append(candidate)
|
|
candidates = new_candidates
|
|
|
|
if self._enabled_ignored_files:
|
|
for glob in self._ignored_files:
|
|
candidates = [x for x in candidates
|
|
if not x['action__path'].match(glob)]
|
|
|
|
for candidate in candidates:
|
|
candidate['is_opened_tree'] = False
|
|
candidate['is_root'] = False
|
|
candidate['is_selected'] = False
|
|
candidate['level'] = base_level
|
|
|
|
return sort(self._sort_method, candidates)
|