mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 16:34:47 +01:00
commit
4e4cfda9f0
5 changed files with 89 additions and 58 deletions
|
@ -11,15 +11,15 @@ from xonsh.tools import TERM_COLORS
|
|||
from xonsh.environ import format_prompt, Env
|
||||
|
||||
builtins.__xonsh_env__ = Env()
|
||||
builtins.__xonsh_env__['PROMPT_TOOLKIT_COLORS'] = {'WHITE': '#ffffff'}
|
||||
builtins.__xonsh_env__['PROMPT_TOOLKIT_COLORS'] = {'WHITE': '#f0f0f0'}
|
||||
|
||||
def test_format_prompt_for_prompt_toolkit():
|
||||
templ = ('>>> {BOLD_BLUE}~/xonsh {WHITE} (main){NO_COLOR}')
|
||||
templ = ('>>> {BOLD_INTENSE_BLUE}~/xonsh {WHITE} {BACKGROUND_RED} {INTENSE_RED}(main){NO_COLOR}')
|
||||
prompt = format_prompt(templ, TERM_COLORS)
|
||||
token_names, color_styles, strings = format_prompt_for_prompt_toolkit(prompt)
|
||||
assert_equal(token_names, ['NO_COLOR', 'BOLD_BLUE', 'WHITE', 'NO_COLOR'])
|
||||
assert_equal(color_styles, ['', 'bold #0000D2', '#ffffff', ''])
|
||||
assert_equal(strings, ['>>> ', '~/xonsh ', ' (main)', ''])
|
||||
assert_equal(token_names, ['NO_COLOR', 'BOLD_INTENSE_BLUE', 'WHITE', 'BACKGROUND_RED', 'INTENSE_RED', 'NO_COLOR'])
|
||||
assert_equal(color_styles, ['noinherit', 'bold #0000d2', '#f0f0f0', 'bg:#800000', 'bg:#800000 #ff1010', 'noinherit'])
|
||||
assert_equal(strings, ['>>> ', '~/xonsh ', ' ', ' ', '(main)', ''])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -99,12 +99,12 @@ def is_callable_default(x):
|
|||
"""Checks if a value is a callable default."""
|
||||
return callable(x) and getattr(x, '_xonsh_callable_default', False)
|
||||
if ON_WINDOWS:
|
||||
DEFAULT_PROMPT = ('{BOLD_GREEN}{user}@{hostname}{BOLD_CYAN} '
|
||||
'{cwd}{branch_color}{curr_branch} '
|
||||
DEFAULT_PROMPT = ('{BOLD_INTENSE_GREEN}{user}@{hostname}{BOLD_INTENSE_CYAN} '
|
||||
'{cwd}{branch_color}{curr_branch}{NO_COLOR} '
|
||||
'{BOLD_WHITE}{prompt_end}{NO_COLOR} ')
|
||||
else:
|
||||
DEFAULT_PROMPT = ('{BOLD_GREEN}{user}@{hostname}{BOLD_BLUE} '
|
||||
'{cwd}{branch_color}{curr_branch} '
|
||||
'{cwd}{branch_color}{curr_branch}{NO_COLOR} '
|
||||
'{BOLD_BLUE}{prompt_end}{NO_COLOR} ')
|
||||
|
||||
DEFAULT_TITLE = '{current_job}{user}@{hostname}: {cwd} | xonsh'
|
||||
|
@ -809,8 +809,14 @@ def dirty_working_directory(cwd=None):
|
|||
|
||||
def branch_color():
|
||||
"""Return red if the current branch is dirty, otherwise green"""
|
||||
return (TERM_COLORS['BOLD_RED'] if dirty_working_directory() else
|
||||
TERM_COLORS['BOLD_GREEN'])
|
||||
return (TERM_COLORS['BOLD_INTENSE_RED'] if dirty_working_directory() else
|
||||
TERM_COLORS['BOLD_INTENSE_GREEN'])
|
||||
|
||||
|
||||
def branch_bg_color():
|
||||
"""Return red if the current branch is dirty, otherwise green"""
|
||||
return (TERM_COLORS['BACKGROUND_RED'] if dirty_working_directory() else
|
||||
TERM_COLORS['BACKGROUND_GREEN'])
|
||||
|
||||
|
||||
def _replace_home(x):
|
||||
|
@ -870,6 +876,7 @@ FORMATTER_DICT = dict(
|
|||
short_cwd=_collapsed_pwd,
|
||||
curr_branch=current_branch,
|
||||
branch_color=branch_color,
|
||||
branch_bg_color=branch_bg_color,
|
||||
current_job=_current_job,
|
||||
**TERM_COLORS)
|
||||
DEFAULT_VALUES['FORMATTER_DICT'] = dict(FORMATTER_DICT)
|
||||
|
|
|
@ -179,7 +179,7 @@ def _xonsh_style(tokens=tuple(), cstyles=tuple()):
|
|||
Token.Aborted: '#888888',
|
||||
})
|
||||
# update with the prompt styles
|
||||
styles.update({t: s for (t, s) in zip(tokens, cstyles)})
|
||||
styles.update(dict(zip(tokens, cstyles)))
|
||||
# Update with with any user styles
|
||||
userstyle = builtins.__xonsh_env__.get('PROMPT_TOOLKIT_STYLES')
|
||||
if userstyle is not None:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Hooks for pygments syntax highlighting."""
|
||||
from pygments.lexer import inherit, bygroups, using, this
|
||||
from pygments.token import Name, Generic, Keyword, Text, String
|
||||
from pygments.token import Name, Generic, Keyword, String
|
||||
from pygments.lexers.shell import BashLexer
|
||||
from pygments.lexers.agile import PythonLexer
|
||||
|
||||
|
@ -61,7 +61,7 @@ class XonshConsoleLexer(PythonLexer):
|
|||
'subproc': SUBPROC_TOKENS,
|
||||
}
|
||||
|
||||
# XonshLexer & XonshSubprocLexer have to refernce each other
|
||||
# XonshLexer & XonshSubprocLexer have to reference each other
|
||||
XonshSubprocLexer.tokens['root'] = [
|
||||
(r'(\$\{)(.*)(\})', bygroups(Keyword, using(XonshLexer), Keyword)),
|
||||
(r'(@\()(.+)(\))', bygroups(Keyword, using(XonshLexer), Keyword)),
|
||||
|
|
114
xonsh/tools.py
114
xonsh/tools.py
|
@ -53,6 +53,7 @@ VER_FULL = sys.version_info[:3]
|
|||
VER_MAJOR_MINOR = sys.version_info[:2]
|
||||
V_MAJOR_MINOR = 'v{0}{1}'.format(*sys.version_info[:2])
|
||||
|
||||
|
||||
def docstring_by_version(**kwargs):
|
||||
"""Sets a docstring by the python version."""
|
||||
doc = kwargs.get(V_MAJOR_MINOR, None)
|
||||
|
@ -764,71 +765,94 @@ class FakeChar(str):
|
|||
return iter(self.char)
|
||||
|
||||
|
||||
RE_HIDDEN_MAX = re.compile('(\001.*?\002)+')
|
||||
COLOR_CODE_SPLIT_RE = re.compile(r'(\001\033\[[\d;m]+\002)')
|
||||
TERM_COLORS_REVERSED = {v: k for k, v in TERM_COLORS.items()}
|
||||
COLOR_NAME_REGEX = re.compile(r'(?:(\w+)_)?(\w+)')
|
||||
|
||||
_PT_COLORS = {
|
||||
'BLACK': '#000000',
|
||||
'RED': '#800000',
|
||||
'GREEN': '#008000',
|
||||
'YELLOW': '#808000',
|
||||
'BLUE': '#000080',
|
||||
'PURPLE': '#800080',
|
||||
'CYAN': '#008080',
|
||||
'WHITE': '#ffffff',
|
||||
'GRAY': '#008080',
|
||||
'INTENSE_RED': '#ff1010',
|
||||
'INTENSE_GREEN': '#00ff18',
|
||||
'INTENSE_YELLOW': '#ffff00',
|
||||
'INTENSE_BLUE': '#0000d2',
|
||||
'INTENSE_PURPLE': '#ff00ff',
|
||||
'INTENSE_CYAN': '#00ffff',
|
||||
'INTENSE_GRAY': '#c0c0c0',
|
||||
None: '',
|
||||
}
|
||||
|
||||
_PT_COLORS_DARK = {'BLACK': '#000000',
|
||||
'RED': '#ff1010',
|
||||
'GREEN': '#00FF18',
|
||||
'YELLOW': '#FFFF00',
|
||||
'BLUE': '#0000D2',
|
||||
'PURPLE': '#FF00FF',
|
||||
'CYAN': '#00FFFF',
|
||||
'WHITE': '#FFFFFF',
|
||||
'GRAY': '#c0c0c0'}
|
||||
_PT_STYLE = {
|
||||
'BOLD': 'bold',
|
||||
'UNDERLINE': 'underline',
|
||||
}
|
||||
|
||||
_PT_COLORS_LIGHT = {'BLACK': '#000000',
|
||||
'RED': '#800000',
|
||||
'GREEN': '#008000',
|
||||
'YELLOW': '#808000',
|
||||
'BLUE': '#000080',
|
||||
'PURPLE': '#800080',
|
||||
'CYAN': '#008080',
|
||||
'WHITE': '#FFFFFF',
|
||||
'GRAY': '#008080'}
|
||||
|
||||
_PT_STYLE = {'BOLD': 'bold',
|
||||
'UNDERLINE': 'underline',
|
||||
'INTENSE': 'italic'}
|
||||
_LAST_BG_COLOR = None
|
||||
|
||||
|
||||
def _make_style(color_name):
|
||||
""" Convert color names to pygments styles codes """
|
||||
global _LAST_BG_COLOR
|
||||
|
||||
colors = _PT_COLORS.copy()
|
||||
# Extend with custom colors
|
||||
colors.update(builtins.__xonsh_env__.get('PROMPT_TOOLKIT_COLORS'))
|
||||
|
||||
if color_name == 'NO_COLOR':
|
||||
_LAST_BG_COLOR = None
|
||||
return 'noinherit'
|
||||
|
||||
qualifiers, name = COLOR_NAME_REGEX.match(color_name).groups()
|
||||
|
||||
if name not in colors:
|
||||
qualifiers = name
|
||||
name = None
|
||||
|
||||
qualifiers = qualifiers.split('_') if qualifiers else []
|
||||
is_bg_color = False
|
||||
style = []
|
||||
for k, v in _PT_STYLE.items():
|
||||
if k in color_name:
|
||||
style.append(v)
|
||||
_custom_colors = builtins.__xonsh_env__.get('PROMPT_TOOLKIT_COLORS')
|
||||
for k, v in _custom_colors.items():
|
||||
if k in color_name:
|
||||
style.append(v)
|
||||
for k, v in _PT_COLORS_DARK.items():
|
||||
if k not in _custom_colors and k in color_name:
|
||||
style.append(v)
|
||||
|
||||
for qualifier in qualifiers:
|
||||
if qualifier == 'INTENSE' and name is not None:
|
||||
name = 'INTENSE_' + name
|
||||
elif qualifier == 'BACKGROUND':
|
||||
is_bg_color = True
|
||||
elif qualifier in _PT_STYLE:
|
||||
style.append(_PT_STYLE[qualifier])
|
||||
|
||||
color = colors[name]
|
||||
if is_bg_color:
|
||||
_LAST_BG_COLOR = color = 'bg:' + color
|
||||
elif _LAST_BG_COLOR:
|
||||
style.append(_LAST_BG_COLOR)
|
||||
|
||||
style.append(color)
|
||||
|
||||
return ' '.join(style)
|
||||
|
||||
|
||||
def get_xonsh_color_names(color_code):
|
||||
""" Makes a reverse lookup in TERM_COLORS """
|
||||
try:
|
||||
return next(k for k, v in TERM_COLORS.items() if v == color_code)
|
||||
except StopIteration:
|
||||
return 'NO_COLOR'
|
||||
|
||||
|
||||
def format_prompt_for_prompt_toolkit(prompt):
|
||||
"""Converts a prompt with color codes to a pygments style and tokens
|
||||
"""
|
||||
parts = RE_HIDDEN_MAX.split(prompt)
|
||||
parts = COLOR_CODE_SPLIT_RE.split(prompt)
|
||||
# ensure that parts is [colorcode, string, colorcode, string,...]
|
||||
if parts and len(parts[0]) == 0:
|
||||
if len(parts[0]) == 0:
|
||||
parts = parts[1:]
|
||||
else:
|
||||
parts.insert(0, '')
|
||||
|
||||
if len(parts) % 2 != 0:
|
||||
parts.append()
|
||||
parts.append('')
|
||||
|
||||
strings = parts[1::2]
|
||||
token_names = [get_xonsh_color_names(c) for c in parts[::2]]
|
||||
token_names = [TERM_COLORS_REVERSED.get(c, 'NO_COLOR') for c in parts[::2]]
|
||||
cstyles = [_make_style(c) for c in token_names]
|
||||
return token_names, cstyles, strings
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue