mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 16:34:47 +01:00
added some color tools, readline seems to work
This commit is contained in:
parent
dfd780c560
commit
1cb9ab832b
5 changed files with 2345 additions and 91 deletions
2256
xonsh/ansi_colors.py
Normal file
2256
xonsh/ansi_colors.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,13 +5,12 @@ from itertools import zip_longest
|
|||
from difflib import SequenceMatcher
|
||||
|
||||
from xonsh import lazyjson
|
||||
from xonsh.tools import TERM_COLORS
|
||||
|
||||
NO_COLOR = TERM_COLORS['NO_COLOR'].replace('\001', '').replace('\002', '')
|
||||
RED = TERM_COLORS['RED'].replace('\001', '').replace('\002', '')
|
||||
GREEN = TERM_COLORS['GREEN'].replace('\001', '').replace('\002', '')
|
||||
BOLD_RED = TERM_COLORS['BOLD_RED'].replace('\001', '').replace('\002', '')
|
||||
BOLD_GREEN = TERM_COLORS['BOLD_GREEN'].replace('\001', '').replace('\002', '')
|
||||
#NO_COLOR = TERM_COLORS['NO_COLOR'].replace('\001', '').replace('\002', '')
|
||||
#RED = TERM_COLORS['RED'].replace('\001', '').replace('\002', '')
|
||||
#GREEN = TERM_COLORS['GREEN'].replace('\001', '').replace('\002', '')
|
||||
#BOLD_RED = TERM_COLORS['BOLD_RED'].replace('\001', '').replace('\002', '')
|
||||
#BOLD_GREEN = TERM_COLORS['BOLD_GREEN'].replace('\001', '').replace('\002', '')
|
||||
|
||||
# intern some strings
|
||||
REPLACE = 'replace'
|
||||
|
|
|
@ -17,7 +17,7 @@ from collections import MutableMapping, MutableSequence, MutableSet, namedtuple
|
|||
|
||||
from xonsh import __version__ as XONSH_VERSION
|
||||
from xonsh.tools import (
|
||||
TERM_COLORS, ON_WINDOWS, ON_MAC, ON_LINUX, ON_ARCH, IS_ROOT,
|
||||
ON_WINDOWS, ON_MAC, ON_LINUX, ON_ARCH, IS_ROOT,
|
||||
always_true, always_false, ensure_string, is_env_path, str_to_env_path,
|
||||
env_path_to_str, is_bool, to_bool, bool_to_str, is_history_tuple, to_history_tuple,
|
||||
history_tuple_to_str, is_float, string_types, is_string, DEFAULT_ENCODING,
|
||||
|
@ -81,6 +81,7 @@ DEFAULT_ENSURERS = {
|
|||
'RAISE_SUBPROC_ERROR': (is_bool, to_bool, bool_to_str),
|
||||
'TEEPTY_PIPE_DELAY': (is_float, float, str),
|
||||
'XONSHRC': (is_env_path, str_to_env_path, env_path_to_str),
|
||||
'XONSH_COLOR_STYLE': (is_string, ensure_string, ensure_string),
|
||||
'XONSH_ENCODING': (is_string, ensure_string, ensure_string),
|
||||
'XONSH_ENCODING_ERRORS': (is_string, ensure_string, ensure_string),
|
||||
'XONSH_HISTORY_SIZE': (is_history_tuple, to_history_tuple, history_tuple_to_str),
|
||||
|
@ -195,6 +196,7 @@ DEFAULT_VALUES = {
|
|||
'xonsh', 'xonshrc'),
|
||||
os.path.expanduser('~/.xonshrc')) if ON_WINDOWS
|
||||
else ('/etc/xonshrc', os.path.expanduser('~/.xonshrc'))),
|
||||
'XONSH_COLOR_STYLE': 'default',
|
||||
'XONSH_CONFIG_DIR': xonsh_config_dir,
|
||||
'XONSH_DATA_DIR': xonsh_data_dir,
|
||||
'XONSH_ENCODING': DEFAULT_ENCODING,
|
||||
|
@ -408,6 +410,9 @@ DEFAULT_DOCS = {
|
|||
'control file if there is a naming collision.', default=(
|
||||
"On Linux & Mac OSX: ('/etc/xonshrc', '~/.xonshrc')\n"
|
||||
"On Windows: ('%ALLUSERSPROFILE%\\xonsh\\xonshrc', '~/.xonshrc')")),
|
||||
'XONSH_COLOR_STYLE': VarDocs(
|
||||
'Sets the color style for xonsh colors. This is a style name, not '
|
||||
'a color map.'),
|
||||
'XONSH_CONFIG_DIR': VarDocs(
|
||||
'This is location where xonsh configuration information is stored.',
|
||||
configurable=False, default="'$XDG_CONFIG_HOME/xonsh'"),
|
||||
|
@ -882,14 +887,14 @@ def dirty_working_directory(cwd=None):
|
|||
|
||||
def branch_color():
|
||||
"""Return red if the current branch is dirty, otherwise green"""
|
||||
return (TERM_COLORS['BOLD_INTENSE_RED'] if dirty_working_directory() else
|
||||
TERM_COLORS['BOLD_INTENSE_GREEN'])
|
||||
return ('{BOLD_INTENSE_RED}' if dirty_working_directory() else
|
||||
'{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'])
|
||||
return ('{BACKGROUND_RED}' if dirty_working_directory() else
|
||||
'{BACKGROUND_GREEN}')
|
||||
|
||||
|
||||
def _replace_home(x):
|
||||
|
@ -961,7 +966,7 @@ FORMATTER_DICT = dict(
|
|||
branch_bg_color=branch_bg_color,
|
||||
current_job=_current_job,
|
||||
env_name=env_name,
|
||||
**TERM_COLORS)
|
||||
)
|
||||
DEFAULT_VALUES['FORMATTER_DICT'] = dict(FORMATTER_DICT)
|
||||
|
||||
_FORMATTER = string.Formatter()
|
||||
|
@ -983,13 +988,18 @@ def is_template_string(template, formatter_dict=None):
|
|||
return included_names <= known_names
|
||||
|
||||
|
||||
def format_prompt(template=DEFAULT_PROMPT, formatter_dict=None):
|
||||
"""Formats a xonsh prompt template string."""
|
||||
template = template() if callable(template) else template
|
||||
def _get_fmtter(formatter_dict=None):
|
||||
if formatter_dict is None:
|
||||
fmtter = builtins.__xonsh_env__.get('FORMATTER_DICT', FORMATTER_DICT)
|
||||
else:
|
||||
fmtter = formatter_dict
|
||||
return fmtter
|
||||
|
||||
|
||||
def format_prompt(template=DEFAULT_PROMPT, formatter_dict=None):
|
||||
"""Formats a xonsh prompt template string."""
|
||||
template = template() if callable(template) else template
|
||||
fmtter = _get_fmtter(formatter_dict)
|
||||
included_names = set(i[1] for i in _FORMATTER.parse(template))
|
||||
fmt = {}
|
||||
for name in included_names:
|
||||
|
@ -1005,12 +1015,47 @@ def format_prompt(template=DEFAULT_PROMPT, formatter_dict=None):
|
|||
return template.format(**fmt)
|
||||
|
||||
|
||||
def partial_format_prompt(template=DEFAULT_PROMPT, formatter_dict=None):
|
||||
"""Formats a xonsh prompt template string."""
|
||||
template = template() if callable(template) else template
|
||||
fmtter = _get_fmtter(formatter_dict)
|
||||
bopen = '{'
|
||||
bclose = '}'
|
||||
colon = ':'
|
||||
expl = '!'
|
||||
toks = []
|
||||
for literal, field, spec, conv in _FORMATTER.parse(template):
|
||||
toks.append(literal)
|
||||
if field is None:
|
||||
continue
|
||||
elif field.startswith('$'):
|
||||
v = builtins.__xonsh_env__[name[1:]]
|
||||
v = _FORMATTER.convert_field(v, conv)
|
||||
v = _FORMATTER.format_field(v, spec)
|
||||
toks.append(v)
|
||||
continue
|
||||
elif field in fmtter:
|
||||
v = fmtter[field]
|
||||
val = v() if callable(v) else v
|
||||
val = '' if val is None else val
|
||||
toks.append(val)
|
||||
else:
|
||||
toks.append(bopen)
|
||||
toks.append(field)
|
||||
if conv is not None and len(conv) > 0:
|
||||
toks.append(expl)
|
||||
toks.append(conv)
|
||||
if spec is not None and len(spec) > 0:
|
||||
toks.append(colon)
|
||||
toks.append(spec)
|
||||
toks.append(bclose)
|
||||
return ''.join(toks)
|
||||
|
||||
|
||||
RE_HIDDEN = re.compile('\001.*?\002')
|
||||
|
||||
def multiline_prompt():
|
||||
def multiline_prompt(curr=''):
|
||||
"""Returns the filler text for the prompt in multiline scenarios."""
|
||||
curr = builtins.__xonsh_env__.get('PROMPT')
|
||||
curr = format_prompt(curr)
|
||||
line = curr.rsplit('\n', 1)[1] if '\n' in curr else curr
|
||||
line = RE_HIDDEN.sub('', line) # gets rid of colors
|
||||
# most prompts end in whitespace, head is the part before that.
|
||||
|
|
|
@ -12,7 +12,9 @@ from collections import deque
|
|||
|
||||
from xonsh import lazyjson
|
||||
from xonsh.base_shell import BaseShell
|
||||
from xonsh.tools import ON_WINDOWS, print_color
|
||||
from xonsh.ansi_colors import partial_color_format
|
||||
from xonsh.environ import partial_format_prompt, multiline_prompt
|
||||
from xonsh.tools import ON_WINDOWS, print_color, print_exception
|
||||
|
||||
RL_COMPLETION_SUPPRESS_APPEND = RL_LIB = None
|
||||
RL_CAN_RESIZE = False
|
||||
|
@ -96,6 +98,7 @@ class ReadlineShell(BaseShell, Cmd):
|
|||
**kwargs)
|
||||
setup_readline()
|
||||
self._current_indent = ''
|
||||
self._current_prompt = ''
|
||||
self.cmdqueue = deque()
|
||||
|
||||
def __del__(self):
|
||||
|
@ -268,7 +271,26 @@ class ReadlineShell(BaseShell, Cmd):
|
|||
# This is needed to support some system where line-wrapping doesn't
|
||||
# work. This is a bug in upstream Python, or possibly readline.
|
||||
RL_LIB.rl_reset_screen_size()
|
||||
return super().prompt
|
||||
#return super().prompt
|
||||
if self.need_more_lines:
|
||||
if self.mlprompt is None:
|
||||
try:
|
||||
self.mlprompt = multiline_prompt(curr=self._current_prompt)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
print_exception()
|
||||
self.mlprompt = '<multiline prompt error> '
|
||||
return self.mlprompt
|
||||
env = builtins.__xonsh_env__ # pylint: disable=no-member
|
||||
p = env.get('PROMPT')
|
||||
try:
|
||||
p = partial_format_prompt(p)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
print_exception()
|
||||
p = partial_color_format(p, style=env.get('XONSH_COLOR_STYLE'),
|
||||
hide=True)
|
||||
self._current_prompt = p
|
||||
self.settitle()
|
||||
return p
|
||||
|
||||
|
||||
class ReadlineHistoryAdder(Thread):
|
||||
|
|
|
@ -223,74 +223,6 @@ def get_sep():
|
|||
os.sep)
|
||||
|
||||
|
||||
TERM_COLORS = {
|
||||
# Reset
|
||||
'NO_COLOR': '\001\033[0m\002', # Text Reset
|
||||
# Regular Colors
|
||||
'BLACK': '\001\033[0;30m\002', # BLACK
|
||||
'RED': '\001\033[0;31m\002', # RED
|
||||
'GREEN': '\001\033[0;32m\002', # GREEN
|
||||
'YELLOW': '\001\033[0;33m\002', # YELLOW
|
||||
'BLUE': '\001\033[0;34m\002', # BLUE
|
||||
'PURPLE': '\001\033[0;35m\002', # PURPLE
|
||||
'CYAN': '\001\033[0;36m\002', # CYAN
|
||||
'WHITE': '\001\033[0;37m\002', # WHITE
|
||||
# Bold
|
||||
'BOLD_BLACK': '\001\033[1;30m\002', # BLACK
|
||||
'BOLD_RED': '\001\033[1;31m\002', # RED
|
||||
'BOLD_GREEN': '\001\033[1;32m\002', # GREEN
|
||||
'BOLD_YELLOW': '\001\033[1;33m\002', # YELLOW
|
||||
'BOLD_BLUE': '\001\033[1;34m\002', # BLUE
|
||||
'BOLD_PURPLE': '\001\033[1;35m\002', # PURPLE
|
||||
'BOLD_CYAN': '\001\033[1;36m\002', # CYAN
|
||||
'BOLD_WHITE': '\001\033[1;37m\002', # WHITE
|
||||
# Underline
|
||||
'UNDERLINE_BLACK': '\001\033[4;30m\002', # BLACK
|
||||
'UNDERLINE_RED': '\001\033[4;31m\002', # RED
|
||||
'UNDERLINE_GREEN': '\001\033[4;32m\002', # GREEN
|
||||
'UNDERLINE_YELLOW': '\001\033[4;33m\002', # YELLOW
|
||||
'UNDERLINE_BLUE': '\001\033[4;34m\002', # BLUE
|
||||
'UNDERLINE_PURPLE': '\001\033[4;35m\002', # PURPLE
|
||||
'UNDERLINE_CYAN': '\001\033[4;36m\002', # CYAN
|
||||
'UNDERLINE_WHITE': '\001\033[4;37m\002', # WHITE
|
||||
# Background
|
||||
'BACKGROUND_BLACK': '\001\033[40m\002', # BLACK
|
||||
'BACKGROUND_RED': '\001\033[41m\002', # RED
|
||||
'BACKGROUND_GREEN': '\001\033[42m\002', # GREEN
|
||||
'BACKGROUND_YELLOW': '\001\033[43m\002', # YELLOW
|
||||
'BACKGROUND_BLUE': '\001\033[44m\002', # BLUE
|
||||
'BACKGROUND_PURPLE': '\001\033[45m\002', # PURPLE
|
||||
'BACKGROUND_CYAN': '\001\033[46m\002', # CYAN
|
||||
'BACKGROUND_WHITE': '\001\033[47m\002', # WHITE
|
||||
# High Intensity
|
||||
'INTENSE_BLACK': '\001\033[0;90m\002', # BLACK
|
||||
'INTENSE_RED': '\001\033[0;91m\002', # RED
|
||||
'INTENSE_GREEN': '\001\033[0;92m\002', # GREEN
|
||||
'INTENSE_YELLOW': '\001\033[0;93m\002', # YELLOW
|
||||
'INTENSE_BLUE': '\001\033[0;94m\002', # BLUE
|
||||
'INTENSE_PURPLE': '\001\033[0;95m\002', # PURPLE
|
||||
'INTENSE_CYAN': '\001\033[0;96m\002', # CYAN
|
||||
'INTENSE_WHITE': '\001\033[0;97m\002', # WHITE
|
||||
# Bold High Intensity
|
||||
'BOLD_INTENSE_BLACK': '\001\033[1;90m\002', # BLACK
|
||||
'BOLD_INTENSE_RED': '\001\033[1;91m\002', # RED
|
||||
'BOLD_INTENSE_GREEN': '\001\033[1;92m\002', # GREEN
|
||||
'BOLD_INTENSE_YELLOW': '\001\033[1;93m\002', # YELLOW
|
||||
'BOLD_INTENSE_BLUE': '\001\033[1;94m\002', # BLUE
|
||||
'BOLD_INTENSE_PURPLE': '\001\033[1;95m\002', # PURPLE
|
||||
'BOLD_INTENSE_CYAN': '\001\033[1;96m\002', # CYAN
|
||||
'BOLD_INTENSE_WHITE': '\001\033[1;97m\002', # WHITE
|
||||
# High Intensity backgrounds
|
||||
'BACKGROUND_INTENSE_BLACK': '\001\033[0;100m\002', # BLACK
|
||||
'BACKGROUND_INTENSE_RED': '\001\033[0;101m\002', # RED
|
||||
'BACKGROUND_INTENSE_GREEN': '\001\033[0;102m\002', # GREEN
|
||||
'BACKGROUND_INTENSE_YELLOW': '\001\033[0;103m\002', # YELLOW
|
||||
'BACKGROUND_INTENSE_BLUE': '\001\033[0;104m\002', # BLUE
|
||||
'BACKGROUND_INTENSE_PURPLE': '\001\033[0;105m\002', # PURPLE
|
||||
'BACKGROUND_INTENSE_CYAN': '\001\033[0;106m\002', # CYAN
|
||||
'BACKGROUND_INTENSE_WHITE': '\001\033[0;107m\002', # WHITE
|
||||
}
|
||||
|
||||
|
||||
def fallback(cond, backup):
|
||||
"""Decorator for returning the object if cond is true and a backup if cond is false.
|
||||
|
@ -756,7 +688,7 @@ def pygments_version():
|
|||
|
||||
|
||||
COLOR_CODE_SPLIT_RE = re.compile(r'(\001\033\[[\d;m]+\002)')
|
||||
TERM_COLORS_REVERSED = {v: k for k, v in TERM_COLORS.items()}
|
||||
#TERM_COLORS_REVERSED = {v: k for k, v in TERM_COLORS.items()}
|
||||
COLOR_NAME_REGEX = re.compile(r'(?:(\w+)_)?(\w+)')
|
||||
|
||||
_PT_COLORS = {
|
||||
|
|
Loading…
Add table
Reference in a new issue