2020-06-13 14:06:35 +08:00
|
|
|
# ============================================================================
|
|
|
|
# FILE: icons.py
|
|
|
|
# AUTHOR: Kristijan Husak <husakkristijan at gmail.com>
|
|
|
|
# License: MIT license
|
|
|
|
# ============================================================================
|
|
|
|
|
|
|
|
import re
|
|
|
|
import typing
|
|
|
|
from pathlib import Path
|
2022-04-11 19:56:49 +08:00
|
|
|
from defx.base.column import Base, Highlights
|
2020-06-13 14:06:35 +08:00
|
|
|
from defx.context import Context
|
|
|
|
from defx.clipboard import ClipboardAction
|
|
|
|
from defx.view import View
|
2022-04-11 19:56:49 +08:00
|
|
|
from defx.util import Nvim, Candidate, len_bytes
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
|
|
|
|
class Column(Base):
|
|
|
|
def __init__(self, vim: Nvim) -> None:
|
|
|
|
super().__init__(vim)
|
|
|
|
self.vim = vim
|
|
|
|
self.name = 'icons'
|
2022-04-11 19:56:49 +08:00
|
|
|
self.has_get_with_highlights = True
|
2020-06-13 14:06:35 +08:00
|
|
|
self.opts = self.vim.call('defx_icons#get')
|
2022-04-11 19:56:49 +08:00
|
|
|
self.icons = self.opts['icons']
|
|
|
|
self.settings = self.opts['settings']
|
|
|
|
self.highlights: typing.Dict[str, typing.Any] = {}
|
|
|
|
self.generate_highlights_map()
|
|
|
|
|
|
|
|
def item_hl(self, name, hi_group) -> None:
|
|
|
|
icon = format(self.icons[name], f'<{self.settings["column_length"]}')
|
|
|
|
self.highlights[name] = (
|
|
|
|
icon,
|
|
|
|
hi_group,
|
|
|
|
len_bytes(icon)
|
|
|
|
)
|
|
|
|
|
|
|
|
def list_hl(self, list_name) -> None:
|
|
|
|
self.highlights[list_name] = {}
|
|
|
|
for name, opts in self.icons[list_name].items():
|
|
|
|
text = re.sub('[^A-Za-z]', '', name)
|
|
|
|
icon = format(opts['icon'], f'<{self.settings["column_length"]}')
|
|
|
|
self.highlights[list_name][name] = (
|
|
|
|
icon,
|
|
|
|
text,
|
|
|
|
len_bytes(icon)
|
|
|
|
)
|
|
|
|
|
|
|
|
def generate_highlights_map(self) -> None:
|
|
|
|
self.item_hl('default_icon', '')
|
|
|
|
self.item_hl('mark_icon', 'DefxIconsMarkIcon')
|
|
|
|
self.item_hl('copy_icon', 'DefxIconsCopyIcon')
|
|
|
|
self.item_hl('link_icon', 'DefxIconsLinkIcon')
|
|
|
|
self.item_hl('move_icon', 'DefxIconsMoveIcon')
|
|
|
|
self.item_hl('directory_icon', 'DefxIconsDirectory')
|
|
|
|
self.item_hl('parent_icon', 'DefxIconsParentDirectory')
|
|
|
|
self.item_hl('directory_symlink_icon', 'DefxIconsSymlinkDirectory')
|
|
|
|
self.item_hl('root_opened_tree_icon', 'DefxIconsOpenedTreeIcon')
|
|
|
|
self.item_hl('nested_opened_tree_icon', 'DefxIconsNestedTreeIcon')
|
|
|
|
self.item_hl('nested_closed_tree_icon', 'DefxIconsClosedTreeIcon')
|
|
|
|
|
|
|
|
self.list_hl('pattern_matches')
|
|
|
|
self.list_hl('exact_matches')
|
|
|
|
self.list_hl('exact_dir_matches')
|
|
|
|
self.list_hl('extensions')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
def on_init(self, view: View, context: Context) -> None:
|
|
|
|
self._context = context
|
|
|
|
self._view = view
|
|
|
|
|
|
|
|
def on_redraw(self, view: View, context: Context) -> None:
|
|
|
|
self._context = context
|
|
|
|
self._view = view
|
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
def get_with_highlights(
|
|
|
|
self, context: Context, candidate: Candidate
|
|
|
|
) -> typing.Tuple[str, Highlights]:
|
2020-06-13 14:06:35 +08:00
|
|
|
path: Path = candidate['action__path']
|
|
|
|
filename = path.name
|
|
|
|
if 'mark' not in context.columns and candidate['is_selected']:
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('mark_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
if self._view and self._view._clipboard.candidates:
|
|
|
|
for clipboard_candidate in self._view._clipboard.candidates:
|
|
|
|
if str(clipboard_candidate['action__path']) == str(path):
|
|
|
|
return self.clipboard_icon()
|
|
|
|
|
|
|
|
if candidate.get('is_root', False):
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('parent_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
if candidate['is_directory']:
|
2022-04-11 19:56:49 +08:00
|
|
|
if filename in self.icons['exact_dir_matches']:
|
|
|
|
return self.icon('exact_dir_matches', filename)
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
if candidate.get('level', 0) > 0:
|
|
|
|
if candidate.get('is_opened_tree'):
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('nested_opened_tree_icon')
|
|
|
|
if path.is_symlink():
|
|
|
|
return self.icon('directory_symlink_icon')
|
|
|
|
return self.icon('nested_closed_tree_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
if candidate.get('is_opened_tree', False):
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('root_opened_tree_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
if path.is_symlink():
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('directory_symlink_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('directory_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
filename = filename.lower()
|
|
|
|
ext = path.suffix[1:].lower()
|
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
for pattern, pattern_data in self.icons['pattern_matches'].items():
|
2020-06-13 14:06:35 +08:00
|
|
|
if re.search(pattern, filename) is not None:
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('pattern_matches', pattern)
|
2020-06-13 14:06:35 +08:00
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
if filename in self.icons['exact_matches']:
|
|
|
|
return self.icon('exact_matches', filename)
|
2020-06-13 14:06:35 +08:00
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
if ext in self.icons['extensions']:
|
|
|
|
return self.icon('extensions', ext)
|
2020-06-13 14:06:35 +08:00
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('default_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
def icon(
|
|
|
|
self, icon_name, nested_icon_name = None
|
|
|
|
) -> typing.Tuple[str, Highlights]:
|
|
|
|
icon = self.highlights[icon_name]
|
|
|
|
if nested_icon_name is not None:
|
|
|
|
icon = icon[nested_icon_name]
|
|
|
|
hl = f'{self.highlight_name}_{icon[1]}'
|
|
|
|
else:
|
|
|
|
hl = icon[1]
|
|
|
|
return (icon[0], [(hl, self.start, icon[2])])
|
2020-06-13 14:06:35 +08:00
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
def length(self, context: Context) -> int:
|
|
|
|
return typing.cast(int, self.settings['column_length'])
|
2020-06-13 14:06:35 +08:00
|
|
|
|
|
|
|
def clipboard_icon(self) -> str:
|
|
|
|
if self._view._clipboard.action == ClipboardAction.COPY:
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('copy_icon')
|
|
|
|
if self._view._clipboard.action == ClipboardAction.LINK:
|
|
|
|
return self.icon('link_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
if self._view._clipboard.action == ClipboardAction.MOVE:
|
2022-04-11 19:56:49 +08:00
|
|
|
return self.icon('move_icon')
|
2020-06-13 14:06:35 +08:00
|
|
|
return ''
|
|
|
|
|
|
|
|
def syn_item(self, name, opt_name, hi_group_name) -> typing.List[str]:
|
|
|
|
commands: typing.List[str] = []
|
2022-04-11 19:56:49 +08:00
|
|
|
commands.append(f'silent! syntax clear {self.highlight_name}_{name}')
|
2020-06-13 14:06:35 +08:00
|
|
|
commands.append((
|
2022-04-11 19:56:49 +08:00
|
|
|
'syntax match {0}_{1} /[{2}]/ contained containedin={3}'
|
|
|
|
).format(self.highlight_name, name, self.icons[opt_name],
|
|
|
|
self.syntax_name))
|
2020-06-13 14:06:35 +08:00
|
|
|
commands.append('highlight default link {0}_{1} {2}'.format(
|
2022-04-11 19:56:49 +08:00
|
|
|
self.highlight_name, name, hi_group_name
|
2020-06-13 14:06:35 +08:00
|
|
|
))
|
|
|
|
return commands
|
|
|
|
|
|
|
|
def syn_list(self, opt) -> typing.List[str]:
|
|
|
|
commands: typing.List[str] = []
|
2022-04-11 19:56:49 +08:00
|
|
|
for name, opts in self.icons[opt].items():
|
2020-06-13 14:06:35 +08:00
|
|
|
text = re.sub('[^A-Za-z]', '', name)
|
2022-04-11 19:56:49 +08:00
|
|
|
commands.append(f'silent! syntax clear {self.highlight_name}_{text}')
|
2020-06-13 14:06:35 +08:00
|
|
|
commands.append((
|
2022-04-11 19:56:49 +08:00
|
|
|
'syntax match {0}_{1} /[{2}]/ contained containedin={3}'
|
|
|
|
).format(self.highlight_name, text, opts['icon'], self.syntax_name))
|
2020-06-13 14:06:35 +08:00
|
|
|
commands.append('highlight default {0}_{1} guifg=#{2} ctermfg={3}'.format(
|
2022-04-11 19:56:49 +08:00
|
|
|
self.highlight_name, text, opts['color'], opts.get('term_color',
|
2020-06-13 14:06:35 +08:00
|
|
|
'NONE')))
|
|
|
|
return commands
|
|
|
|
|
|
|
|
def highlight_commands(self) -> typing.List[str]:
|
|
|
|
commands: typing.List[str] = []
|
|
|
|
|
2022-04-11 19:56:49 +08:00
|
|
|
if not self.settings['enable_syntax_highlight']:
|
2020-06-13 14:06:35 +08:00
|
|
|
return commands
|
|
|
|
|
|
|
|
commands += self.syn_item('icon_mark', 'mark_icon', 'DefxIconsMarkIcon')
|
|
|
|
commands += self.syn_item('icon_copy', 'copy_icon', 'DefxIconsCopyIcon')
|
2022-04-11 19:56:49 +08:00
|
|
|
commands += self.syn_item('icon_link', 'link_icon', 'DefxIconsLinkIcon')
|
2020-06-13 14:06:35 +08:00
|
|
|
commands += self.syn_item('icon_move', 'move_icon', 'DefxIconsMoveIcon')
|
|
|
|
|
|
|
|
commands += self.syn_item('directory', 'directory_icon', 'DefxIconsDirectory')
|
|
|
|
commands += self.syn_item('parent_directory', 'parent_icon', 'DefxIconsParentDirectory')
|
|
|
|
commands += self.syn_item('symlink_directory', 'directory_symlink_icon', 'DefxIconsSymlinkDirectory')
|
|
|
|
commands += self.syn_item('root_opened_tree_icon', 'root_opened_tree_icon', 'DefxIconsOpenedTreeIcon')
|
|
|
|
commands += self.syn_item('nested_opened_tree_icon', 'nested_opened_tree_icon', 'DefxIconsNestedTreeIcon')
|
|
|
|
commands += self.syn_item('nested_closed_tree_icon', 'nested_closed_tree_icon', 'DefxIconsClosedTreeIcon')
|
|
|
|
|
|
|
|
commands += self.syn_list('pattern_matches')
|
|
|
|
commands += self.syn_list('exact_matches')
|
|
|
|
commands += self.syn_list('exact_dir_matches')
|
|
|
|
commands += self.syn_list('extensions')
|
|
|
|
|
|
|
|
return commands
|