Make using tui.operations more convenient
This commit is contained in:
parent
ffc6e65392
commit
d133ffac25
@ -12,11 +12,6 @@ from kitty.key_encoding import DOWN, ESCAPE, PRESS, REPEAT, UP
|
|||||||
|
|
||||||
from ..tui.handler import Handler
|
from ..tui.handler import Handler
|
||||||
from ..tui.loop import Loop
|
from ..tui.loop import Loop
|
||||||
from ..tui.operations import (
|
|
||||||
bell, clear_screen, scroll_screen, set_cursor_position, set_cursor_visible,
|
|
||||||
set_default_colors, set_line_wrapping, set_scrolling_region,
|
|
||||||
set_window_title
|
|
||||||
)
|
|
||||||
from .collect import create_collection, data_for_path
|
from .collect import create_collection, data_for_path
|
||||||
from .config import init_config
|
from .config import init_config
|
||||||
from .patch import Differ
|
from .patch import Differ
|
||||||
@ -62,31 +57,31 @@ class DiffHandler(Handler):
|
|||||||
return self.screen_size.rows - 1
|
return self.screen_size.rows - 1
|
||||||
|
|
||||||
def set_scrolling_region(self):
|
def set_scrolling_region(self):
|
||||||
self.write(set_scrolling_region(self.screen_size, 0, self.num_lines - 2))
|
self.cmd.set_scrolling_region(self.screen_size, 0, self.num_lines - 2)
|
||||||
|
|
||||||
def scroll_lines(self, amt=1):
|
def scroll_lines(self, amt=1):
|
||||||
new_pos = max(0, min(self.scroll_pos + amt, self.max_scroll_pos))
|
new_pos = max(0, min(self.scroll_pos + amt, self.max_scroll_pos))
|
||||||
if new_pos == self.scroll_pos:
|
if new_pos == self.scroll_pos:
|
||||||
self.write(bell())
|
self.cmd.bell()
|
||||||
return
|
return
|
||||||
if abs(new_pos - self.scroll_pos) >= self.num_lines - 1:
|
if abs(new_pos - self.scroll_pos) >= self.num_lines - 1:
|
||||||
self.scroll_pos = new_pos
|
self.scroll_pos = new_pos
|
||||||
self.draw_screen()
|
self.draw_screen()
|
||||||
return
|
return
|
||||||
self.enforce_cursor_state()
|
self.enforce_cursor_state()
|
||||||
self.write(scroll_screen(amt))
|
self.cmd.scroll_screen(amt)
|
||||||
self.scroll_pos = new_pos
|
self.scroll_pos = new_pos
|
||||||
if amt < 0:
|
if amt < 0:
|
||||||
self.write(set_cursor_position(0, 0))
|
self.cmd.set_cursor_position(0, 0)
|
||||||
self.draw_lines(-amt)
|
self.draw_lines(-amt)
|
||||||
else:
|
else:
|
||||||
self.write(set_cursor_position(0, self.num_lines - amt))
|
self.cmd.set_cursor_position(0, self.num_lines - amt)
|
||||||
self.draw_lines(amt, self.num_lines - amt)
|
self.draw_lines(amt, self.num_lines - amt)
|
||||||
|
|
||||||
def init_terminal_state(self):
|
def init_terminal_state(self):
|
||||||
self.write(set_line_wrapping(False))
|
self.cmd.set_line_wrapping(False)
|
||||||
self.write(set_window_title('kitty +diff'))
|
self.cmd.set_window_title('kitty +diff')
|
||||||
self.write(set_default_colors(self.opts.foreground, self.opts.background))
|
self.cmd.set_default_colors(self.opts.foreground, self.opts.background)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.init_terminal_state()
|
self.init_terminal_state()
|
||||||
@ -95,11 +90,11 @@ class DiffHandler(Handler):
|
|||||||
self.create_collection()
|
self.create_collection()
|
||||||
|
|
||||||
def enforce_cursor_state(self):
|
def enforce_cursor_state(self):
|
||||||
self.write(set_cursor_visible(self.state > DIFFED))
|
self.cmd.set_cursor_visible(self.state > DIFFED)
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
self.write(set_cursor_visible(True))
|
self.cmd.set_cursor_visible(True)
|
||||||
self.write(set_default_colors())
|
self.cmd.set_default_colors()
|
||||||
|
|
||||||
def draw_lines(self, num, offset=0):
|
def draw_lines(self, num, offset=0):
|
||||||
offset += self.scroll_pos
|
offset += self.scroll_pos
|
||||||
@ -116,16 +111,17 @@ class DiffHandler(Handler):
|
|||||||
def draw_screen(self):
|
def draw_screen(self):
|
||||||
self.enforce_cursor_state()
|
self.enforce_cursor_state()
|
||||||
if self.state < DIFFED:
|
if self.state < DIFFED:
|
||||||
self.write(clear_screen())
|
self.cmd.clear_screen()
|
||||||
self.write(_('Calculating diff, please wait...'))
|
self.write(_('Calculating diff, please wait...'))
|
||||||
return
|
return
|
||||||
self.write(clear_screen())
|
self.cmd.clear_screen()
|
||||||
self.draw_lines(self.num_lines)
|
self.draw_lines(self.num_lines)
|
||||||
self.draw_status_line()
|
self.draw_status_line()
|
||||||
|
|
||||||
def draw_status_line(self):
|
def draw_status_line(self):
|
||||||
self.write(set_cursor_position(0, self.num_lines))
|
self.cmd.set_cursor_position(0, self.num_lines)
|
||||||
self.write('\033[K:')
|
self.cmd.clear_to_eol()
|
||||||
|
self.write(':')
|
||||||
|
|
||||||
def on_text(self, text, in_bracketed_paste=False):
|
def on_text(self, text, in_bracketed_paste=False):
|
||||||
if text == 'q':
|
if text == 'q':
|
||||||
|
|||||||
@ -3,12 +3,16 @@
|
|||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
|
from kittens.tui.operations import commander
|
||||||
|
|
||||||
|
|
||||||
class Handler:
|
class Handler:
|
||||||
|
|
||||||
def _initialize(self, screen_size, quit_loop, wakeup, start_job):
|
def _initialize(self, screen_size, quit_loop, wakeup, start_job):
|
||||||
self.screen_size, self.quit_loop = screen_size, quit_loop
|
self.screen_size, self.quit_loop = screen_size, quit_loop
|
||||||
self.wakeup = wakeup
|
self.wakeup = wakeup
|
||||||
self.start_job = start_job
|
self.start_job = start_job
|
||||||
|
self.cmd = commander(self)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.initialize()
|
self.initialize()
|
||||||
|
|||||||
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
from kitty.rgb import Color, color_as_sharp, to_color
|
from kitty.rgb import Color, color_as_sharp, to_color
|
||||||
from kitty.terminfo import string_capabilities
|
|
||||||
|
|
||||||
S7C1T = '\033 F'
|
S7C1T = '\033 F'
|
||||||
SAVE_CURSOR = '\0337'
|
SAVE_CURSOR = '\0337'
|
||||||
@ -36,46 +36,45 @@ MODES = dict(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def set_mode(which, private=True):
|
def set_mode(which, private=True) -> str:
|
||||||
num, private = MODES[which]
|
num, private = MODES[which]
|
||||||
return '\033[{}{}h'.format(private, num)
|
return '\033[{}{}h'.format(private, num)
|
||||||
|
|
||||||
|
|
||||||
def reset_mode(which):
|
def reset_mode(which) -> str:
|
||||||
num, private = MODES[which]
|
num, private = MODES[which]
|
||||||
return '\033[{}{}l'.format(private, num)
|
return '\033[{}{}l'.format(private, num)
|
||||||
|
|
||||||
|
|
||||||
def simple_capability(name):
|
def clear_screen() -> str:
|
||||||
ans = string_capabilities[name].replace(r'\E', '\033')
|
return '\033[H\033[2J'
|
||||||
return lambda: ans
|
|
||||||
|
|
||||||
|
|
||||||
clear_screen = simple_capability('clear')
|
def clear_to_eol() -> str:
|
||||||
clear_to_bottom = simple_capability('ed')
|
return '\033[K'
|
||||||
|
|
||||||
|
|
||||||
def bell():
|
def bell() -> str:
|
||||||
return '\a'
|
return '\a'
|
||||||
|
|
||||||
|
|
||||||
def set_window_title(value):
|
def set_window_title(value) -> str:
|
||||||
return ('\033]2;' + value.replace('\033', '').replace('\x9c', '') + '\033\\')
|
return ('\033]2;' + value.replace('\033', '').replace('\x9c', '') + '\033\\')
|
||||||
|
|
||||||
|
|
||||||
def set_line_wrapping(yes_or_no):
|
def set_line_wrapping(yes_or_no) -> str:
|
||||||
return (set_mode if yes_or_no else reset_mode)('DECAWM')
|
return (set_mode if yes_or_no else reset_mode)('DECAWM')
|
||||||
|
|
||||||
|
|
||||||
def set_cursor_visible(yes_or_no):
|
def set_cursor_visible(yes_or_no) -> str:
|
||||||
return (set_mode if yes_or_no else reset_mode)('DECTCEM')
|
return (set_mode if yes_or_no else reset_mode)('DECTCEM')
|
||||||
|
|
||||||
|
|
||||||
def set_cursor_position(x, y): # (0, 0) is top left
|
def set_cursor_position(x, y) -> str: # (0, 0) is top left
|
||||||
return '\033[{};{}H'.format(y + 1, x + 1)
|
return '\033[{};{}H'.format(y + 1, x + 1)
|
||||||
|
|
||||||
|
|
||||||
def set_scrolling_region(screen_size, top=None, bottom=None):
|
def set_scrolling_region(screen_size, top=None, bottom=None) -> str:
|
||||||
if top is None:
|
if top is None:
|
||||||
top = 0
|
top = 0
|
||||||
if bottom is None:
|
if bottom is None:
|
||||||
@ -87,7 +86,7 @@ def set_scrolling_region(screen_size, top=None, bottom=None):
|
|||||||
return '\033[{};{}r'.format(top + 1, bottom + 1)
|
return '\033[{};{}r'.format(top + 1, bottom + 1)
|
||||||
|
|
||||||
|
|
||||||
def scroll_screen(amt=1):
|
def scroll_screen(amt=1) -> str:
|
||||||
return '\033[' + str(abs(amt)) + ('T' if amt < 0 else 'S')
|
return '\033[' + str(abs(amt)) + ('T' if amt < 0 else 'S')
|
||||||
|
|
||||||
|
|
||||||
@ -107,20 +106,20 @@ def color_code(color, intense=False, base=30):
|
|||||||
return e
|
return e
|
||||||
|
|
||||||
|
|
||||||
def sgr(*parts):
|
def sgr(*parts) -> str:
|
||||||
return '\033[{}m'.format(';'.join(parts))
|
return '\033[{}m'.format(';'.join(parts))
|
||||||
|
|
||||||
|
|
||||||
def colored(text, color, intense=False, reset_to=None, reset_to_intense=False):
|
def colored(text, color, intense=False, reset_to=None, reset_to_intense=False) -> str:
|
||||||
e = color_code(color, intense)
|
e = color_code(color, intense)
|
||||||
return '\033[{}m{}\033[{}m'.format(e, text, 39 if reset_to is None else color_code(reset_to, reset_to_intense))
|
return '\033[{}m{}\033[{}m'.format(e, text, 39 if reset_to is None else color_code(reset_to, reset_to_intense))
|
||||||
|
|
||||||
|
|
||||||
def faint(text):
|
def faint(text) -> str:
|
||||||
return colored(text, 'black', True)
|
return colored(text, 'black', True)
|
||||||
|
|
||||||
|
|
||||||
def styled(text, fg=None, bg=None, fg_intense=False, bg_intense=False, italic=None, bold=None, underline=None, underline_color=None, reverse=None):
|
def styled(text, fg=None, bg=None, fg_intense=False, bg_intense=False, italic=None, bold=None, underline=None, underline_color=None, reverse=None) -> str:
|
||||||
start, end = [], []
|
start, end = [], []
|
||||||
if fg is not None:
|
if fg is not None:
|
||||||
start.append(color_code(fg, fg_intense))
|
start.append(color_code(fg, fg_intense))
|
||||||
@ -192,7 +191,7 @@ def alternate_screen(f=None):
|
|||||||
print(reset_mode('ALTERNATE_SCREEN'), end='', file=f)
|
print(reset_mode('ALTERNATE_SCREEN'), end='', file=f)
|
||||||
|
|
||||||
|
|
||||||
def set_default_colors(fg=None, bg=None):
|
def set_default_colors(fg=None, bg=None) -> str:
|
||||||
ans = ''
|
ans = ''
|
||||||
if fg is None:
|
if fg is None:
|
||||||
ans += '\x1b]110\x1b\\'
|
ans += '\x1b]110\x1b\\'
|
||||||
@ -203,3 +202,20 @@ def set_default_colors(fg=None, bg=None):
|
|||||||
else:
|
else:
|
||||||
ans += '\x1b]11;{}\x1b\\'.format(color_as_sharp(bg if isinstance(bg, Color) else to_color(bg)))
|
ans += '\x1b]11;{}\x1b\\'.format(color_as_sharp(bg if isinstance(bg, Color) else to_color(bg)))
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
all_cmds = tuple(
|
||||||
|
(name, obj) for name, obj in globals().items()
|
||||||
|
if hasattr(obj, '__annotations__') and obj.__annotations__.get('return') is str)
|
||||||
|
|
||||||
|
|
||||||
|
def writer(handler, func):
|
||||||
|
@wraps(func)
|
||||||
|
def f(self, *a, **kw):
|
||||||
|
handler.write(func(*a, **kw))
|
||||||
|
return f
|
||||||
|
|
||||||
|
|
||||||
|
def commander(handler):
|
||||||
|
ans = {name: writer(handler, obj) for name, obj in all_cmds}
|
||||||
|
return type('CMD', (), ans)()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user