Replace name and module keys with function key

Fixes #1031
This commit is contained in:
ZyX 2014-08-29 22:38:26 +04:00
parent 5bd543ae89
commit 41476544ca
21 changed files with 267 additions and 190 deletions

View File

@ -64,8 +64,9 @@ Common configuration is a subdictionary that is a value of ``common`` key in
``paths`` ``paths``
Defines additional paths which will be searched for modules when using Defines additional paths which will be searched for modules when using
:ref:`module segment option <config-themes-seg-module>`. Paths defined here :ref:`function segment option <config-themes-seg-function>` or :ref:`Vim
have priority when searching for modules. local_themes option <config-ext-local_themes>`. Paths defined here have
priority when searching for modules.
.. _config-common-log: .. _config-common-log:
@ -283,7 +284,8 @@ ascii Theme without any unicode characters at all
.. _config-themes-default_module: .. _config-themes-default_module:
``default_module`` ``default_module``
Python module where segments will be looked by default. Python module where segments will be looked by default. Defaults to
``powerline.segments.{ext}``.
``spaces`` ``spaces``
Defines number of spaces just before the divider (on the right side) or just Defines number of spaces just before the divider (on the right side) or just
@ -325,8 +327,8 @@ ascii Theme without any unicode characters at all
.. _config-themes-segment_data: .. _config-themes-segment_data:
``segment_data`` ``segment_data``
A dict where keys are segment names or strings ``{module}.{name}``. Used to A dict where keys are segment names or strings ``{module}.{function}``. Used
specify default values for various keys: to specify default values for various keys:
:ref:`after <config-themes-seg-after>`, :ref:`after <config-themes-seg-after>`,
:ref:`before <config-themes-seg-before>`, :ref:`before <config-themes-seg-before>`,
:ref:`contents <config-themes-seg-contents>` (only for string segments :ref:`contents <config-themes-seg-contents>` (only for string segments
@ -335,8 +337,8 @@ ascii Theme without any unicode characters at all
Key :ref:`args <config-themes-seg-args>` (only for function and Key :ref:`args <config-themes-seg-args>` (only for function and
segments_list segments) is handled specially: unlike other values it is segments_list segments) is handled specially: unlike other values it is
merged with all other values, except that a single ``{module}.{name}`` key merged with all other values, except that a single ``{module}.{function}``
if found prevents merging all ``{name}`` values. key if found prevents merging all ``{function}`` values.
When using :ref:`local themes <config-ext-local_themes>` values of these When using :ref:`local themes <config-ext-local_themes>` values of these
keys are first searched in the segment description, then in ``segment_data`` keys are first searched in the segment description, then in ``segment_data``
@ -372,8 +374,8 @@ ascii Theme without any unicode characters at all
``filler`` or ``segments_list``: ``filler`` or ``segments_list``:
``function`` ``function``
The segment contents is the return value of the function defined The segment contents is the return value of the function defined in
in the :ref:`name option <config-themes-seg-name>`. the :ref:`function option <config-themes-seg-function>`.
``string`` ``string``
A static string segment where the contents is defined in the A static string segment where the contents is defined in the
@ -382,22 +384,31 @@ ascii Theme without any unicode characters at all
option <config-themes-seg-highlight_group>`. option <config-themes-seg-highlight_group>`.
``segments_list`` ``segments_list``
Sub-list of segments. This list only allows :ref:`name Sub-list of segments. This list only allows :ref:`function
<config-themes-seg-name>`, :ref:`segments <config-themes-seg-function>`, :ref:`segments
<config-themes-seg-segments>` and :ref:`args <config-themes-seg-segments>` and :ref:`args
<config-themes-seg-args>` options. <config-themes-seg-args>` options.
.. _config-themes-seg-module:
``module``
Function module, only required for function segments. Defaults to
``powerline.segments.{extension}``. Default is overriden by
:ref:`default_module theme option <config-themes-default_module>`.
.. _config-themes-seg-name: .. _config-themes-seg-name:
``name`` ``name``
Function name, only required for function and list segments. Segment name. If present allows referring to this segment in
:ref:`segment_data <config-themes-segment_data>` dictionary by this
name. If not ``string`` segments may not be referred there at all and
``function`` and ``segments_list`` segments may be referred there using
either ``{module}.{function_name}`` or ``{function_name}``, whichever
will be found first. Function name is taken from :ref:`function key
<config-themes-seg-function>`.
.. note::
If present prevents ``function`` key from acting as a segment name.
.. _config-themes-seg-function:
``function``
Function used to get segment contents, in format ``{module}.{function}``
or ``{function}``. If ``{module}`` is omitted :ref:`default_module
option <config-themes-default_module>` is used.
.. _config-themes-seg-highlight_group: .. _config-themes-seg-highlight_group:

View File

@ -3,7 +3,7 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"name": "virtualenv", "function": "virtualenv",
"priority": 10 "priority": 10
}, },
{ {
@ -13,8 +13,7 @@
"highlight_group": ["prompt"] "highlight_group": ["prompt"]
}, },
{ {
"name": "prompt_count", "function": "powerline.segments.ipython.prompt_count",
"module": "powerline.segments.ipython",
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {

View File

@ -1,5 +1,5 @@
{ {
"default_module": "powerline.segments.common", "default_module": "powerline.segments.ipython",
"segments": { "segments": {
"left": [ "left": [
{ {
@ -11,8 +11,7 @@
"highlight_group": ["prompt"] "highlight_group": ["prompt"]
}, },
{ {
"name": "prompt_count", "function": "prompt_count",
"module": "powerline.segments.ipython",
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {

View File

@ -1,4 +1,5 @@
{ {
"default_module": "powerline.segments.ipython",
"segments": { "segments": {
"left": [ "left": [
{ {
@ -9,8 +10,7 @@
"highlight_group": ["prompt"] "highlight_group": ["prompt"]
}, },
{ {
"name": "prompt_count", "function": "prompt_count",
"module": "powerline.segments.ipython",
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {

View File

@ -3,7 +3,7 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"name": "continuation" "function": "continuation"
} }
], ],
"right": [ "right": [

View File

@ -3,40 +3,36 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"module": "powerline.segments.shell", "function": "powerline.segments.shell.mode"
"name": "mode"
}, },
{ {
"name": "hostname", "function": "hostname",
"priority": 10 "priority": 10
}, },
{ {
"name": "user", "function": "user",
"priority": 30 "priority": 30
}, },
{ {
"name": "virtualenv", "function": "virtualenv",
"priority": 50 "priority": 50
}, },
{ {
"module": "powerline.segments.shell", "function": "powerline.segments.shell.cwd",
"name": "cwd",
"priority": 10 "priority": 10
}, },
{ {
"module": "powerline.segments.shell", "function": "powerline.segments.shell.jobnum",
"name": "jobnum",
"priority": 20 "priority": 20
} }
], ],
"right": [ "right": [
{ {
"module": "powerline.segments.shell", "function": "powerline.segments.shell.last_pipe_status",
"name": "last_pipe_status",
"priority": 10 "priority": 10
}, },
{ {
"name": "branch", "function": "branch",
"priority": 40 "priority": 40
} }
] ]

View File

@ -3,34 +3,31 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"name": "hostname", "function": "hostname",
"priority": 10 "priority": 10
}, },
{ {
"name": "user", "function": "user",
"priority": 30 "priority": 30
}, },
{ {
"name": "virtualenv", "function": "virtualenv",
"priority": 50 "priority": 50
}, },
{ {
"name": "branch", "function": "branch",
"priority": 40 "priority": 40
}, },
{ {
"module": "powerline.segments.shell", "function": "powerline.segments.shell.cwd",
"name": "cwd",
"priority": 10 "priority": 10
}, },
{ {
"module": "powerline.segments.shell", "function": "powerline.segments.shell.jobnum",
"name": "jobnum",
"priority": 20 "priority": 20
}, },
{ {
"module": "powerline.segments.shell", "function": "powerline.segments.shell.last_status",
"name": "last_status",
"priority": 10 "priority": 10
} }
] ]

View File

@ -3,26 +3,26 @@
"segments": { "segments": {
"right": [ "right": [
{ {
"name": "uptime", "function": "uptime",
"priority": 50 "priority": 50
}, },
{ {
"name": "system_load", "function": "system_load",
"priority": 50 "priority": 50
}, },
{ {
"name": "date", "function": "date",
"before": "" "before": ""
}, },
{ {
"name": "date", "function": "date",
"args": { "args": {
"format": "%H:%M", "format": "%H:%M",
"istime": true "istime": true
} }
}, },
{ {
"name": "hostname" "function": "hostname"
} }
] ]
} }

View File

@ -2,67 +2,65 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"name": "mode", "function": "mode",
"exclude_modes": ["nc"] "exclude_modes": ["nc"]
}, },
{ {
"name": "visual_range", "function": "visual_range",
"include_modes": ["v", "V", "^V", "s", "S", "^S"], "include_modes": ["v", "V", "^V", "s", "S", "^S"],
"priority": 10 "priority": 10
}, },
{ {
"name": "paste_indicator", "function": "paste_indicator",
"exclude_modes": ["nc"], "exclude_modes": ["nc"],
"priority": 10 "priority": 10
}, },
{ {
"name": "branch", "function": "branch",
"exclude_modes": ["nc"], "exclude_modes": ["nc"],
"priority": 30 "priority": 30
}, },
{ {
"name": "readonly_indicator", "function": "readonly_indicator",
"draw_soft_divider": false, "draw_soft_divider": false,
"after": " " "after": " "
}, },
{ {
"name": "file_scheme", "function": "file_scheme",
"priority": 20 "priority": 20
}, },
{ {
"name": "file_directory", "function": "file_directory",
"priority": 40, "priority": 40,
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {
"name": "file_name", "function": "file_name",
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {
"name": "file_vcs_status", "function": "file_vcs_status",
"before": " ", "before": " ",
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {
"name": "modified_indicator", "function": "modified_indicator",
"before": " " "before": " "
}, },
{ {
"exclude_modes": ["i", "R", "Rv"], "exclude_modes": ["i", "R", "Rv"],
"name": "trailing_whitespace", "function": "trailing_whitespace",
"display": false, "display": false,
"priority": 60 "priority": 60
}, },
{ {
"exclude_modes": ["nc"], "exclude_modes": ["nc"],
"module": "powerline.segments.vim.plugin.syntastic", "function": "powerline.segments.vim.plugin.syntastic.syntastic",
"name": "syntastic",
"priority": 50 "priority": 50
}, },
{ {
"exclude_modes": ["nc"], "exclude_modes": ["nc"],
"module": "powerline.segments.vim.plugin.tagbar", "function": "powerline.segments.vim.plugin.tagbar.current_tag",
"name": "current_tag",
"draw_soft_divider": false, "draw_soft_divider": false,
"priority": 50 "priority": 50
}, },
@ -76,23 +74,23 @@
], ],
"right": [ "right": [
{ {
"name": "file_format", "function": "file_format",
"draw_soft_divider": false, "draw_soft_divider": false,
"exclude_modes": ["nc"], "exclude_modes": ["nc"],
"priority": 60 "priority": 60
}, },
{ {
"name": "file_encoding", "function": "file_encoding",
"exclude_modes": ["nc"], "exclude_modes": ["nc"],
"priority": 60 "priority": 60
}, },
{ {
"name": "file_type", "function": "file_type",
"exclude_modes": ["nc"], "exclude_modes": ["nc"],
"priority": 60 "priority": 60
}, },
{ {
"name": "line_percent", "function": "line_percent",
"priority": 50, "priority": 50,
"width": 4, "width": 4,
"align": "r" "align": "r"
@ -103,13 +101,13 @@
"highlight_group": ["line_current_symbol", "line_current"] "highlight_group": ["line_current_symbol", "line_current"]
}, },
{ {
"name": "line_current", "function": "line_current",
"draw_soft_divider": false, "draw_soft_divider": false,
"width": 3, "width": 3,
"align": "r" "align": "r"
}, },
{ {
"name": "virtcol_current", "function": "virtcol_current",
"draw_soft_divider": false, "draw_soft_divider": false,
"priority": 20, "priority": 20,
"before": ":", "before": ":",

View File

@ -2,7 +2,7 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"name": "file_name", "function": "file_name",
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {
@ -15,7 +15,7 @@
], ],
"right": [ "right": [
{ {
"name": "line_percent", "function": "line_percent",
"priority": 30, "priority": 30,
"width": 4, "width": 4,
"align": "r" "align": "r"
@ -26,7 +26,7 @@
"highlight_group": ["line_current_symbol", "line_current"] "highlight_group": ["line_current_symbol", "line_current"]
}, },
{ {
"name": "line_current", "function": "line_current",
"draw_soft_divider": false, "draw_soft_divider": false,
"width": 3, "width": 3,
"align": "r" "align": "r"

View File

@ -3,7 +3,7 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"name": "ctrlp", "function": "ctrlp",
"args": { "args": {
"side": "left" "side": "left"
} }
@ -18,7 +18,7 @@
], ],
"right": [ "right": [
{ {
"name": "ctrlp", "function": "ctrlp",
"args": { "args": {
"side": "right" "side": "right"
} }

View File

@ -3,7 +3,7 @@
"segments": { "segments": {
"left": [ "left": [
{ {
"name": "nerdtree" "function": "nerdtree"
}, },
{ {
"type": "string", "type": "string",

View File

@ -12,7 +12,7 @@
"highlight_group": ["file_name"] "highlight_group": ["file_name"]
}, },
{ {
"name": "window_title", "function": "window_title",
"draw_soft_divider": false "draw_soft_divider": false
}, },
{ {
@ -30,7 +30,7 @@
"highlight_group": ["line_current_symbol", "line_current"] "highlight_group": ["line_current_symbol", "line_current"]
}, },
{ {
"name": "line_current", "function": "line_current",
"draw_soft_divider": false, "draw_soft_divider": false,
"width": 3, "width": 3,
"align": "r" "align": "r"

View File

@ -4,39 +4,38 @@
"left": [ "left": [
{ {
"type": "segment_list", "type": "segment_list",
"module": "powerline.listers.vim", "function": "powerline.listers.vim.tabbuflister",
"name": "tabbuflister",
"segments": [ "segments": [
{ {
"name": "tabnr", "function": "tabnr",
"after": " ", "after": " ",
"exclude_modes": ["tab", "buf", "buf_nc"], "exclude_modes": ["tab", "buf", "buf_nc"],
"priority": 5 "priority": 5
}, },
{ {
"name": "bufnr", "function": "bufnr",
"after": " ", "after": " ",
"exclude_modes": ["tab", "buf", "tab_nc"], "exclude_modes": ["tab", "buf", "tab_nc"],
"priority": 5 "priority": 5
}, },
{ {
"name": "file_directory", "function": "file_directory",
"priority": 40 "priority": 40
}, },
{ {
"name": "file_name", "function": "file_name",
"args": { "args": {
"display_no_file": true "display_no_file": true
}, },
"priority": 10 "priority": 10
}, },
{ {
"name": "tab_modified_indicator", "function": "tab_modified_indicator",
"exclude_modes": ["buf", "buf_nc"], "exclude_modes": ["buf", "buf_nc"],
"priority": 5 "priority": 5
}, },
{ {
"name": "modified_indicator", "function": "modified_indicator",
"exclude_modes": ["tab", "tab_nc"], "exclude_modes": ["tab", "tab_nc"],
"priority": 5 "priority": 5
} }
@ -52,7 +51,7 @@
], ],
"right": [ "right": [
{ {
"name": "single_tab" "function": "single_tab"
} }
] ]
} }

View File

@ -3,22 +3,22 @@
"segments": { "segments": {
"right": [ "right": [
{ {
"name": "weather", "function": "weather",
"priority": 50 "priority": 50
}, },
{ {
"name": "date", "function": "date",
"before": "" "before": ""
}, },
{ {
"name": "date", "function": "date",
"args": { "args": {
"format": "%H:%M", "format": "%H:%M",
"istime": true "istime": true
} }
}, },
{ {
"name": "email_imap_alert", "function": "email_imap_alert",
"priority": 10, "priority": 10,
"args": { "args": {
"username": "", "username": "",

View File

@ -808,16 +808,16 @@ generic_keys = set((
'display' 'display'
)) ))
type_keys = { type_keys = {
'function': set(('args', 'module', 'draw_inner_divider')), 'function': set(('function', 'args', 'draw_inner_divider')),
'string': set(('contents', 'type', 'highlight_group', 'divider_highlight_group')), 'string': set(('contents', 'type', 'highlight_group', 'divider_highlight_group')),
'filler': set(('type', 'highlight_group', 'divider_highlight_group')), 'filler': set(('type', 'highlight_group', 'divider_highlight_group')),
'segment_list': set(('segments', 'module', 'args', 'type')), 'segment_list': set(('function', 'segments', 'args', 'type')),
} }
required_keys = { required_keys = {
'function': set(('name',)), 'function': set(('function',)),
'string': set(()), 'string': set(()),
'filler': set(), 'filler': set(),
'segment_list': set(('name', 'segments',)), 'segment_list': set(('function', 'segments',)),
} }
highlight_keys = set(('highlight_group', 'name')) highlight_keys = set(('highlight_group', 'name'))
@ -887,8 +887,17 @@ def check_segment_module(module, data, context, echoerr):
return True, False, False return True, False, False
def get_function_strings(function_name, context, ext):
if '.' in function_name:
module, function_name = function_name.rpartition('.')[::2]
else:
module = context[0][1].get(
'default_module', MarkedUnicode('powerline.segments.' + ext, None))
return module, function_name
def check_full_segment_data(segment, data, context, echoerr): def check_full_segment_data(segment, data, context, echoerr):
if 'name' not in segment: if 'name' not in segment and 'function' not in segment:
return True, False, False return True, False, False
ext = data['ext'] ext = data['ext']
@ -899,11 +908,17 @@ def check_full_segment_data(segment, data, context, echoerr):
else: else:
top_segment_data = data['ext_theme_configs'].get(main_theme_name, {}).get('segment_data', {}) top_segment_data = data['ext_theme_configs'].get(main_theme_name, {}).get('segment_data', {})
names = [segment['name']]
if segment.get('type', 'function') == 'function': if segment.get('type', 'function') == 'function':
module = segment.get('module', context[0][1].get('default_module', MarkedUnicode( function_name = segment.get('function')
'powerline.segments.' + ext, None))) if function_name:
names.insert(0, unicode(module) + '.' + unicode(names[0])) module, function_name = get_function_strings(function_name, context, ext)
names = [module + '.' + function_name, function_name]
else:
names = []
elif segment.get('name'):
names = [segment['name']]
else:
return True, False, False
segment_copy = segment.copy() segment_copy = segment.copy()
@ -921,15 +936,9 @@ def check_full_segment_data(segment, data, context, echoerr):
return check_key_compatibility(segment_copy, data, context, echoerr) return check_key_compatibility(segment_copy, data, context, echoerr)
def import_segment(name, data, context, echoerr, module=None): def import_segment(name, data, context, echoerr, module):
context_has_marks(context) context_has_marks(context)
havemarks(name) havemarks(name, module)
if not module:
module = context[-2][1].get(
'module', context[0][1].get(
'default_module', MarkedUnicode(
'powerline.segments.' + data['ext'], None)))
havemarks(module)
with WithPath(data['import_paths']): with WithPath(data['import_paths']):
try: try:
@ -956,11 +965,12 @@ def import_segment(name, data, context, echoerr, module=None):
return func return func
def check_segment_name(name, data, context, echoerr): def check_segment_function(function_name, data, context, echoerr):
havemarks(name) havemarks(function_name)
ext = data['ext'] ext = data['ext']
module, function_name = get_function_strings(function_name, context, ext)
if context[-2][1].get('type', 'function') == 'function': if context[-2][1].get('type', 'function') == 'function':
func = import_segment(name, data, context, echoerr) func = import_segment(function_name, data, context, echoerr, module=module)
if not func: if not func:
return True, False, True return True, False, True
@ -974,7 +984,7 @@ def check_segment_name(name, data, context, echoerr):
D_H_G_USED_STR = 'Divider highlight group used: ' D_H_G_USED_STR = 'Divider highlight group used: '
LDHGUS = len(D_H_G_USED_STR) LDHGUS = len(D_H_G_USED_STR)
pointer = 0 pointer = 0
mark_name = '<{0} docstring>'.format(name) mark_name = '<{0} docstring>'.format(function_name)
for i, line in enumerate(func.__doc__.split('\n')): for i, line in enumerate(func.__doc__.split('\n')):
if H_G_USED_STR in line: if H_G_USED_STR in line:
idx = line.index(H_G_USED_STR) + LHGUS idx = line.index(H_G_USED_STR) + LHGUS
@ -1000,7 +1010,7 @@ def check_segment_name(name, data, context, echoerr):
'found highlight group {0} not defined in the following colorschemes: {1}\n' 'found highlight group {0} not defined in the following colorschemes: {1}\n'
'(Group name was obtained from function documentation.)' '(Group name was obtained from function documentation.)'
).format(divider_hl_group, list_sep.join(r)), ).format(divider_hl_group, list_sep.join(r)),
problem_mark=name.mark problem_mark=function_name.mark
) )
hadproblem = True hadproblem = True
@ -1039,7 +1049,7 @@ def check_segment_name(name, data, context, echoerr):
'found highlight groups list ({0}) with all groups not defined in some colorschemes\n' 'found highlight groups list ({0}) with all groups not defined in some colorschemes\n'
'(Group names were taken from function documentation.)' '(Group names were taken from function documentation.)'
).format(list_sep.join((h[0] for h in required_pack))), ).format(list_sep.join((h[0] for h in required_pack))),
problem_mark=name.mark problem_mark=function_name.mark
) )
for r, h in zip(rs, required_pack): for r, h in zip(rs, required_pack):
echoerr( echoerr(
@ -1049,7 +1059,7 @@ def check_segment_name(name, data, context, echoerr):
) )
hadproblem = True hadproblem = True
else: else:
r = hl_exists(name, data, context, echoerr, allow_gradients=True) r = hl_exists(function_name, data, context, echoerr, allow_gradients=True)
if r: if r:
echoerr( echoerr(
context='Error while checking theme (key {key})'.format(key=context_key(context)), context='Error while checking theme (key {key})'.format(key=context_key(context)),
@ -1058,27 +1068,27 @@ def check_segment_name(name, data, context, echoerr):
'(If not specified otherwise in documentation, ' '(If not specified otherwise in documentation, '
'highlight group for function segments\n' 'highlight group for function segments\n'
'is the same as the function name.)' 'is the same as the function name.)'
).format(name, list_sep.join(r)), ).format(function_name, list_sep.join(r)),
problem_mark=name.mark problem_mark=function_name.mark
) )
hadproblem = True hadproblem = True
return True, False, hadproblem return True, False, hadproblem
elif context[-2][1].get('type') != 'segment_list': elif context[-2][1].get('type') != 'segment_list':
if name not in context[0][1].get('segment_data', {}): if function_name not in context[0][1].get('segment_data', {}):
main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None) main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
if data['theme'] == main_theme_name: if data['theme'] == main_theme_name:
main_theme = {} main_theme = {}
else: else:
main_theme = data['ext_theme_configs'].get(main_theme_name, {}) main_theme = data['ext_theme_configs'].get(main_theme_name, {})
if ( if (
name not in main_theme.get('segment_data', {}) function_name not in main_theme.get('segment_data', {})
and name not in data['ext_theme_configs'].get('__main__', {}).get('segment_data', {}) and function_name not in data['ext_theme_configs'].get('__main__', {}).get('segment_data', {})
and not any(((name in theme.get('segment_data', {})) for theme in data['top_themes'].values())) and not any(((function_name in theme.get('segment_data', {})) for theme in data['top_themes'].values()))
): ):
echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)),
problem='found useless use of name key (such name is not present in theme/segment_data)', problem='found useless use of name key (such name is not present in theme/segment_data)',
problem_mark=name.mark) problem_mark=function_name.mark)
return True, False, False return True, False, False
@ -1192,16 +1202,22 @@ def check_segment_data_key(key, data, context, echoerr):
for segments in theme.get('segments', {}).values(): for segments in theme.get('segments', {}).values():
for segment in segments: for segment in segments:
if 'name' in segment: if 'name' in segment:
if has_module_name: if key == segment['name']:
module = segment.get('module', theme.get('default_module', 'powerline.segments.' + ext)) found = True
full_name = unicode(module) + '.' + unicode(segment['name']) break
if key == full_name: else:
found = True function_name = segment.get('function')
break if function_name:
else: module, function_name = get_function_strings(function_name, ((None, theme),), ext)
if key == segment['name']: if has_module_name:
found = True full_name = module + '.' + function_name
break if key == full_name:
found = True
break
else:
if key == function_name:
found = True
break
if found: if found:
break break
if found: if found:
@ -1288,9 +1304,11 @@ def check_args(get_functions, args, data, context, echoerr):
def get_one_segment_function(data, context, echoerr): def get_one_segment_function(data, context, echoerr):
name = context[-2][1].get('name') ext = data['ext']
if name: function_name = context[-2][1].get('function')
func = import_segment(name, data, context, echoerr) if function_name:
module, function_name = get_function_strings(function_name, context, ext)
func = import_segment(function_name, data, context, echoerr, module=module)
if func: if func:
yield func yield func
@ -1307,14 +1325,14 @@ def get_all_possible_functions(data, context, echoerr):
for segments in theme_config.get('segments', {}).values(): for segments in theme_config.get('segments', {}).values():
for segment in segments: for segment in segments:
if segment.get('type', 'function') == 'function': if segment.get('type', 'function') == 'function':
module = segment.get( function_name = segment.get('function')
'module', current_name = segment.get('name')
theme_config.get('default_module', MarkedUnicode( if function_name:
'powerline.segments.' + data['ext'], None)) module, function_name = get_function_strings(function_name, ((None, theme_config),), ext)
) if current_name == name or function_name == name:
func = import_segment(name, data, context, echoerr, module=module) func = import_segment(function_name, data, context, echoerr, module=module)
if func: if func:
yield func yield func
args_spec = Spec( args_spec = Spec(
@ -1326,7 +1344,8 @@ segment_module_spec = Spec().type(unicode).func(check_segment_module).optional()
sub_segments_spec = Spec() sub_segments_spec = Spec()
segment_spec = Spec( segment_spec = Spec(
type=Spec().oneof(type_keys).optional(), type=Spec().oneof(type_keys).optional(),
name=Spec().re('^[a-zA-Z_]\w*$').func(check_segment_name).optional(), name=Spec().re('^[a-zA-Z_]\w*$').optional(),
function=Spec().re('^(\w+\.)*[a-zA-Z_]\w*$').func(check_segment_function).optional(),
exclude_modes=Spec().list(vim_mode_spec()).optional(), exclude_modes=Spec().list(vim_mode_spec()).optional(),
include_modes=Spec().list(vim_mode_spec()).optional(), include_modes=Spec().list(vim_mode_spec()).optional(),
draw_hard_divider=Spec().type(bool).optional(), draw_hard_divider=Spec().type(bool).optional(),

View File

@ -4,34 +4,35 @@ from __future__ import absolute_import, unicode_literals, division, print_functi
from powerline.lib.watcher import create_file_watcher from powerline.lib.watcher import create_file_watcher
def list_segment_key_values(segment, theme_configs, segment_data, key, module=None, default=None): def list_segment_key_values(segment, theme_configs, segment_data, key, function_name=None, name=None, module=None, default=None):
try: try:
yield segment[key] yield segment[key]
except KeyError: except KeyError:
pass pass
try: found_module_key = False
name = segment['name'] for theme_config in theme_configs:
except KeyError: try:
pass segment_data = theme_config['segment_data']
else: except KeyError:
found_module_key = False pass
for theme_config in theme_configs: else:
try: if function_name and not name:
segment_data = theme_config['segment_data']
except KeyError:
pass
else:
if module: if module:
try: try:
yield segment_data[module + '.' + name][key] yield segment_data[module + '.' + function_name][key]
found_module_key = True found_module_key = True
except KeyError: except KeyError:
pass pass
if not found_module_key: if not found_module_key:
try: try:
yield segment_data[name][key] yield segment_data[function_name][key]
except KeyError: except KeyError:
pass pass
if name:
try:
yield segment_data[name][key]
except KeyError:
pass
if segment_data is not None: if segment_data is not None:
try: try:
yield segment_data[key] yield segment_data[key]
@ -58,26 +59,31 @@ def get_segment_key(merge, *args, **kwargs):
def get_function(data, segment): def get_function(data, segment):
segment_module = str(segment.get('module', data['default_module'])) function_name = segment['function']
function = data['get_module_attr'](segment_module, segment['name'], prefix='segment_generator') if '.' in function_name:
module, function_name = function_name.rpartition('.')[::2]
else:
module = data['default_module']
function = data['get_module_attr'](module, function_name, prefix='segment_generator')
if not function: if not function:
raise ImportError('Failed to obtain segment function') raise ImportError('Failed to obtain segment function')
return None, function, segment_module return None, function, module, function_name, segment.get('name')
def get_string(data, segment): def get_string(data, segment):
return data['get_key'](False, segment, None, 'contents'), None, None name = segment.get('name')
return data['get_key'](False, segment, None, None, name, 'contents'), None, None, None, name
def get_filler(data, segment): def get_filler(data, segment):
return None, None, None return None, None, None, None, None
segment_getters = { segment_getters = {
"function": get_function, 'function': get_function,
"string": get_string, 'string': get_string,
"filler": get_filler, 'filler': get_filler,
"segment_list": get_function, 'segment_list': get_function,
} }
@ -185,8 +191,8 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
'segment_data': None, 'segment_data': None,
} }
def get_key(merge, segment, module, key, default=None): def get_key(merge, segment, module, function_name, name, key, default=None):
return get_segment_key(merge, segment, theme_configs, data['segment_data'], key, module, default) return get_segment_key(merge, segment, theme_configs, data['segment_data'], key, function_name, name, module, default)
data['get_key'] = get_key data['get_key'] = get_key
def get(segment, side): def get(segment, side):
@ -197,12 +203,12 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
raise TypeError('Unknown segment type: {0}'.format(segment_type)) raise TypeError('Unknown segment type: {0}'.format(segment_type))
try: try:
contents, _contents_func, module = get_segment_info(data, segment) contents, _contents_func, module, function_name, name = get_segment_info(data, segment)
except Exception as e: except Exception as e:
pl.exception('Failed to generate segment from {0!r}: {1}', segment, str(e), prefix='segment_generator') pl.exception('Failed to generate segment from {0!r}: {1}', segment, str(e), prefix='segment_generator')
return None return None
if not get_key(False, segment, module, 'display', True): if not get_key(False, segment, module, function_name, name, 'display', True):
return None return None
segment_datas = getattr(_contents_func, 'powerline_segment_datas', None) segment_datas = getattr(_contents_func, 'powerline_segment_datas', None)
@ -213,12 +219,12 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
pass pass
if segment_type == 'function': if segment_type == 'function':
highlight_group = [module + '.' + segment['name'], segment['name']] highlight_group = [module + '.' + function_name, function_name]
else: else:
highlight_group = segment.get('highlight_group') or segment.get('name') highlight_group = segment.get('highlight_group') or name
if segment_type in ('function', 'segment_list'): if segment_type in ('function', 'segment_list'):
args = dict(((str(k), v) for k, v in get_key(True, segment, module, 'args', {}).items())) args = dict(((str(k), v) for k, v in get_key(True, segment, module, function_name, name, 'args', {}).items()))
if segment_type == 'segment_list': if segment_type == 'segment_list':
# Handle startup and shutdown of _contents_func? # Handle startup and shutdown of _contents_func?
@ -227,7 +233,7 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
for subsegment in segment['segments'] for subsegment in segment['segments']
] ]
return { return {
'name': segment.get('name'), 'name': name or function_name,
'type': segment_type, 'type': segment_type,
'highlight_group': None, 'highlight_group': None,
'divider_highlight_group': None, 'divider_highlight_group': None,
@ -278,12 +284,12 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
contents_func = None contents_func = None
return { return {
'name': segment.get('name'), 'name': name or function_name,
'type': segment_type, 'type': segment_type,
'highlight_group': highlight_group, 'highlight_group': highlight_group,
'divider_highlight_group': None, 'divider_highlight_group': None,
'before': get_key(False, segment, module, 'before', ''), 'before': get_key(False, segment, module, function_name, name, 'before', ''),
'after': get_key(False, segment, module, 'after', ''), 'after': get_key(False, segment, module, function_name, name, 'after', ''),
'contents_func': contents_func, 'contents_func': contents_func,
'contents': contents, 'contents': contents,
'priority': segment.get('priority', None), 'priority': segment.get('priority', None),

View File

@ -123,7 +123,7 @@ config = {
'segments': { 'segments': {
'left': [ 'left': [
{ {
'name': 'environment', 'function': 'environment',
'args': { 'args': {
'variable': 'TEST', 'variable': 'TEST',
}, },
@ -442,8 +442,7 @@ class TestSegmentAttributes(TestRender):
config['themes/test/default']['segments'] = { config['themes/test/default']['segments'] = {
'left': [ 'left': [
{ {
'name': 'm1', 'function': 'bar.m1'
'module': 'bar'
} }
] ]
} }
@ -469,14 +468,57 @@ class TestSegmentAttributes(TestRender):
config['themes/test/default']['segments'] = { config['themes/test/default']['segments'] = {
'left': [ 'left': [
{ {
'name': 'm1', 'function': 'bar.m1'
'module': 'bar'
} }
] ]
} }
self.assertRenderEqual(p, '{56} pl;{6-}>>{--}') self.assertRenderEqual(p, '{56} pl;{6-}>>{--}')
class TestSegmentData(TestRender):
@add_args
def test_segment_data(self, p, config):
def m1(**kwargs):
return 'S'
def m2(**kwargs):
return 'S'
sys.modules['bar'] = Args(m1=m1, m2=m2)
config['themes/powerline']['segment_data'] = {
'm1': {
'before': '1'
},
'bar.m2': {
'before': '2'
},
'n': {
'before': '3'
},
'm2': {
'before': '4'
},
}
config['themes/test/default']['segments'] = {
'left': [
{
'function': 'bar.m1'
},
{
'function': 'bar.m1',
'name': 'n'
},
{
'function': 'bar.m2',
'name': 'n'
},
{
'function': 'bar.m2'
}
]
}
self.assertRenderEqual(p, '{56} 1S{56}>{56}3S{610}>>{910}3S{910}>{910}2S{10-}>>{--}')
class TestVim(TestCase): class TestVim(TestCase):
def test_environ_update(self): def test_environ_update(self):
# Regression test: test that segment obtains environment from vim, not # Regression test: test that segment obtains environment from vim, not

View File

@ -1,5 +1,6 @@
#!/usr/bin/vim -S #!/usr/bin/vim -S
set encoding=utf-8 set encoding=utf-8
let g:powerline_config_path = expand('<sfile>:p:h:h') . '/powerline/config_files'
tabedit abc tabedit abc
tabedit def tabedit def
try try

View File

@ -138,10 +138,16 @@ class TestConfig(TestCase):
old_cwd = None old_cwd = None
saved_get_config_paths = None
def setUpModule(): def setUpModule():
global old_cwd global old_cwd
global saved_get_config_paths
import powerline
saved_get_config_paths = powerline.get_config_paths
path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'powerline', 'config_files')
powerline.get_config_paths = lambda: [path]
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path'))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
old_cwd = os.getcwd() old_cwd = os.getcwd()
from powerline.segments import vim from powerline.segments import vim
@ -150,6 +156,9 @@ def setUpModule():
def tearDownModule(): def tearDownModule():
global old_cwd global old_cwd
global saved_get_config_paths
import powerline
powerline.get_config_paths = saved_get_config_paths
os.chdir(old_cwd) os.chdir(old_cwd)
old_cwd = None old_cwd = None
sys.path.pop(0) sys.path.pop(0)

View File

@ -1,5 +1,6 @@
#!/usr/bin/vim -S #!/usr/bin/vim -S
set encoding=utf-8 set encoding=utf-8
let g:powerline_config_path = expand('<sfile>:p:h:h') . '/powerline/config_files'
source powerline/bindings/vim/plugin/powerline.vim source powerline/bindings/vim/plugin/powerline.vim
edit abc edit abc
tabedit def tabedit def