Work on search by name in unicode input
This commit is contained in:
parent
2cc8402458
commit
f0d4ad16d2
@ -2,6 +2,8 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from kitty.terminfo import string_capabilities
|
from kitty.terminfo import string_capabilities
|
||||||
|
|
||||||
S7C1T = b'\033 F'
|
S7C1T = b'\033 F'
|
||||||
@ -56,18 +58,50 @@ def set_line_wrapping(yes_or_no):
|
|||||||
|
|
||||||
STANDARD_COLORS = {name: i for i, name in enumerate(
|
STANDARD_COLORS = {name: i for i, name in enumerate(
|
||||||
'black red green yellow blue magenta cyan gray'.split())}
|
'black red green yellow blue magenta cyan gray'.split())}
|
||||||
|
UNDERLINE_STYLES = {name: i + 1 for i, name in enumerate(
|
||||||
|
'straight double curly'.split())}
|
||||||
|
|
||||||
|
|
||||||
|
def _color(color, intense=False, base=30):
|
||||||
|
if isinstance(color, str):
|
||||||
|
e = str((base + 60 if intense else base) + STANDARD_COLORS[color])
|
||||||
|
elif isinstance(color, int):
|
||||||
|
e = '{}:5:{}'.format(base + 8, max(0, min(color, 255)))
|
||||||
|
else:
|
||||||
|
e = '{}:2:{}:{}:{}'.format(base + 8, *color)
|
||||||
|
return e
|
||||||
|
|
||||||
|
|
||||||
def colored(text, color, intense=False):
|
def colored(text, color, intense=False):
|
||||||
if isinstance(color, str):
|
e = _color(color, intense)
|
||||||
e = (90 if intense else 30) + STANDARD_COLORS[color]
|
|
||||||
elif isinstance(color, int):
|
|
||||||
e = '38:5:{}'.format(max(0, min(color, 255)))
|
|
||||||
else:
|
|
||||||
e = '38:2:{}:{}:{}'.format(*color)
|
|
||||||
return '\033[{}m{}\033[39m'.format(e, text)
|
return '\033[{}m{}\033[39m'.format(e, text)
|
||||||
|
|
||||||
|
|
||||||
|
def styled(text, fg=None, bg=None, fg_intense=False, bg_intense=False, italic=False, bold=False, underline=None, underline_color=None):
|
||||||
|
start, end = [], []
|
||||||
|
if fg is not None:
|
||||||
|
start.append(_color(fg, fg_intense))
|
||||||
|
end.append('39')
|
||||||
|
if bg is not None:
|
||||||
|
start.append(_color(bg, bg_intense, 40))
|
||||||
|
end.append('49')
|
||||||
|
if underline_color is not None:
|
||||||
|
if isinstance(underline_color, str):
|
||||||
|
underline_color = STANDARD_COLORS[underline_color]
|
||||||
|
start.append(_color(underline_color, base=50))
|
||||||
|
end.append('59')
|
||||||
|
if underline is not None:
|
||||||
|
start.append('4:{}'.format(UNDERLINE_STYLES[underline]))
|
||||||
|
end.append('4:0')
|
||||||
|
if italic:
|
||||||
|
start.append('3'), end.append('23')
|
||||||
|
if bold:
|
||||||
|
start.append('1'), end.append('21')
|
||||||
|
if not start:
|
||||||
|
return text
|
||||||
|
return '\033[{}m{}\033[{}m'.format(';'.join(start), text, ';'.join(end))
|
||||||
|
|
||||||
|
|
||||||
def init_state(alternate_screen=True):
|
def init_state(alternate_screen=True):
|
||||||
ans = (
|
ans = (
|
||||||
S7C1T + SAVE_CURSOR + SAVE_PRIVATE_MODE_VALUES + reset_mode('LNM') +
|
S7C1T + SAVE_CURSOR + SAVE_PRIVATE_MODE_VALUES + reset_mode('LNM') +
|
||||||
@ -92,3 +126,10 @@ def reset_state(normal_screen=True):
|
|||||||
ans += RESTORE_PRIVATE_MODE_VALUES
|
ans += RESTORE_PRIVATE_MODE_VALUES
|
||||||
ans += RESTORE_CURSOR
|
ans += RESTORE_CURSOR
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def cursor(write):
|
||||||
|
write(SAVE_CURSOR)
|
||||||
|
yield
|
||||||
|
write(RESTORE_CURSOR)
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from functools import lru_cache
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
|
||||||
from kitty.fast_data_types import wcswidth
|
from kitty.fast_data_types import wcswidth
|
||||||
@ -11,9 +12,28 @@ from kitty.key_encoding import ESCAPE, backspace_key, enter_key
|
|||||||
from ..tui.handler import Handler
|
from ..tui.handler import Handler
|
||||||
from ..tui.loop import Loop
|
from ..tui.loop import Loop
|
||||||
from ..tui.operations import (
|
from ..tui.operations import (
|
||||||
clear_screen, colored, set_line_wrapping, set_window_title
|
clear_screen, colored, cursor, set_line_wrapping, set_window_title, styled
|
||||||
)
|
)
|
||||||
|
|
||||||
|
HEX, NAME = 0, 1
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache()
|
||||||
|
def points_for_word(w):
|
||||||
|
from .unicode_names import codepoints_for_word
|
||||||
|
return codepoints_for_word(w.lower())
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache()
|
||||||
|
def name(cp):
|
||||||
|
from .unicode_names import name_for_codepoint
|
||||||
|
if isinstance(cp, str):
|
||||||
|
cp = ord(cp[0])
|
||||||
|
return (name_for_codepoint(cp) or '').capitalize()
|
||||||
|
|
||||||
|
|
||||||
|
FAINT = 242
|
||||||
|
|
||||||
|
|
||||||
class UnicodeInput(Handler):
|
class UnicodeInput(Handler):
|
||||||
|
|
||||||
@ -21,24 +41,43 @@ class UnicodeInput(Handler):
|
|||||||
self.current_input = ''
|
self.current_input = ''
|
||||||
self.current_char = None
|
self.current_char = None
|
||||||
self.prompt_template = '{}> '
|
self.prompt_template = '{}> '
|
||||||
|
self.choice_line = ''
|
||||||
|
self.mode = HEX
|
||||||
self.update_prompt()
|
self.update_prompt()
|
||||||
|
|
||||||
def update_current_char(self):
|
def update_current_char(self):
|
||||||
try:
|
if self.mode is HEX:
|
||||||
code = int(self.current_input, 16)
|
try:
|
||||||
if code <= 32 or code == 127 or 128 <= code <= 159:
|
code = int(self.current_input, 16)
|
||||||
|
if code <= 32 or code == 127 or 128 <= code <= 159:
|
||||||
|
self.current_char = None
|
||||||
|
else:
|
||||||
|
self.current_char = chr(code)
|
||||||
|
except Exception:
|
||||||
self.current_char = None
|
self.current_char = None
|
||||||
else:
|
else:
|
||||||
self.current_char = chr(code)
|
|
||||||
except Exception:
|
|
||||||
self.current_char = None
|
self.current_char = None
|
||||||
|
parts = self.current_input.split()
|
||||||
|
if parts and parts[0]:
|
||||||
|
codepoints = points_for_word(parts[0])
|
||||||
|
for word in parts[1:]:
|
||||||
|
pts = points_for_word(word)
|
||||||
|
if pts:
|
||||||
|
codepoints &= pts
|
||||||
|
if codepoints:
|
||||||
|
codepoints = tuple(sorted(codepoints))
|
||||||
|
self.current_char = chr(codepoints[0])
|
||||||
|
# name_map = {c: name(c) for c in codepoints}
|
||||||
|
|
||||||
def update_prompt(self):
|
def update_prompt(self):
|
||||||
self.update_current_char()
|
self.update_current_char()
|
||||||
if self.current_char is None:
|
if self.current_char is None:
|
||||||
c, color = '??', 'red'
|
c, color = '??', 'red'
|
||||||
|
self.choice_line = ''
|
||||||
else:
|
else:
|
||||||
c, color = self.current_char, 'green'
|
c, color = self.current_char, 'green'
|
||||||
|
self.choice_line = _('Chosen:') + ' {} ({}) {}'.format(
|
||||||
|
colored(c, 'green'), hex(ord(c))[2:], styled(name(c) or '', italic=True, fg=FAINT))
|
||||||
w = wcswidth(c)
|
w = wcswidth(c)
|
||||||
self.prompt = self.prompt_template.format(colored(c, color))
|
self.prompt = self.prompt_template.format(colored(c, color))
|
||||||
self.promt_len = w + len(self.prompt_template) - 2
|
self.promt_len = w + len(self.prompt_template) - 2
|
||||||
@ -51,16 +90,28 @@ class UnicodeInput(Handler):
|
|||||||
|
|
||||||
def draw_screen(self):
|
def draw_screen(self):
|
||||||
self.write(clear_screen())
|
self.write(clear_screen())
|
||||||
self.print(_('Enter the hex code for the unicode character'))
|
if self.mode is HEX:
|
||||||
|
self.print(styled(_('Press the / key to search by character name'), fg=FAINT, italic=True))
|
||||||
|
self.print(_('Enter the hex code for the character'))
|
||||||
|
else:
|
||||||
|
self.print(_('Enter words from the name of the character'))
|
||||||
self.write(self.prompt)
|
self.write(self.prompt)
|
||||||
self.write(self.current_input)
|
self.write(self.current_input)
|
||||||
|
with cursor(self.write):
|
||||||
|
self.print()
|
||||||
|
if self.choice_line:
|
||||||
|
self.print(self.choice_line)
|
||||||
|
self.print()
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
self.update_prompt()
|
self.update_prompt()
|
||||||
self.draw_screen()
|
self.draw_screen()
|
||||||
|
|
||||||
def on_text(self, text, in_bracketed_paste):
|
def on_text(self, text, in_bracketed_paste):
|
||||||
self.current_input += text
|
if self.mode is HEX and text == '/':
|
||||||
|
self.mode = NAME
|
||||||
|
else:
|
||||||
|
self.current_input += text
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
def on_key(self, key_event):
|
def on_key(self, key_event):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user