def update(self, *data) -> None: di.instances = {} original(*data) screen = self.screen blocks = list( filter(lambda b: b.get("val") is not None, [{ **block, **{ "val": di.get(block.get("val")) } } for block in self.status_blocks])) status_len = sum( [len(b.get('del')) + len(b.get('val')) + 2 for b in blocks]) self.screen.cursor.bg = as_rgb(color_as_int(self.draw_data.default_bg)) self.screen.draw(' ' * (screen.columns - screen.cursor.x - status_len)) for block in blocks: bg = color_as_int(to_color(block.get('bg'))) self.screen.cursor.fg = screen.cursor.bg self.screen.cursor.bg = as_rgb(bg) screen.draw(block.get("del")) fg = color_as_int(to_color(block.get("fg"))) self.screen.cursor.fg = as_rgb(fg) screen.draw(" " + block.get("val") + " ")
def set_default_colors(fg=None, bg=None): ans = '' if fg is None: ans += '\x1b]110\x1b\\' else: ans += '\x1b]10;{}\x1b\\'.format(color_as_sharp(to_color(fg))) if bg is None: ans += '\x1b]111\x1b\\' else: ans += '\x1b]11;{}\x1b\\'.format(color_as_sharp(to_color(bg))) return ans
def set_default_colors(fg=None, bg=None) -> str: ans = '' if fg is None: ans += '\x1b]110\x1b\\' else: ans += '\x1b]10;{}\x1b\\'.format( color_as_sharp(fg if isinstance(fg, Color) else to_color(fg))) if bg is None: ans += '\x1b]111\x1b\\' else: ans += '\x1b]11;{}\x1b\\'.format( color_as_sharp(bg if isinstance(bg, Color) else to_color(bg))) return ans
def test_to_color(self): for x in 'xxx #12 #1234 rgb:a/b'.split(): self.assertIsNone(to_color(x)) def c(spec, r=0, g=0, b=0, a=0): c = to_color(spec) self.ae(c.red, r) self.ae(c.green, g) self.ae(c.blue, b) self.ae(c.alpha, a) c('#eee', 0xee, 0xee, 0xee) c('#234567', 0x23, 0x45, 0x67) c('#abcabcdef', 0xab, 0xab, 0xde) c('rgb:e/e/e', 0xee, 0xee, 0xee) c('rgb:23/45/67', 0x23, 0x45, 0x67) c('rgb:abc/abc/def', 0xab, 0xab, 0xde) c('red', 0xff) self.ae(int(Color(1, 2, 3)), 0x10203) base = Color(12, 12, 12) a = Color(23, 23, 23) b = Color(100, 100, 100) self.assertLess(base.contrast(a), base.contrast(b)) self.ae(Color(1, 2, 3).as_sgr, ':2:1:2:3') self.ae(Color(1, 2, 3).as_sharp, '#010203') self.ae(Color(1, 2, 3, 4).as_sharp, '#04010203') self.ae(Color(1, 2, 3, 4).rgb, 0x10203)
def item(which, num): nonlocal ans if which is None: ans += '\x1b]1{}\x1b\\'.format(num) else: ans += '\x1b]{};{}\x1b\\'.format( num, color_as_sharp( which if isinstance(which, Color) else to_color(which)))
def item(which: Optional[Union[Color, str]], num: int) -> None: nonlocal ans if which is None: ans += '\x1b]1{}\x1b\\'.format(num) else: if isinstance(which, Color): q = color_as_sharp(which) else: x = to_color(which) assert x is not None q = color_as_sharp(x) ans += '\x1b]{};{}\x1b\\'.format(num, q)
def test_to_color(self): for x in 'xxx #12 #1234 rgb:a/b'.split(): self.assertIsNone(to_color(x)) def c(spec, r=0, g=0, b=0): self.ae(tuple(to_color(spec)), (r, g, b)) c('#eee', 0xee, 0xee, 0xee) c('#234567', 0x23, 0x45, 0x67) c('#abcabcdef', 0xab, 0xab, 0xde) c('rgb:e/e/e', 0xee, 0xee, 0xee) c('rgb:23/45/67', 0x23, 0x45, 0x67) c('rgb:abc/abc/def', 0xab, 0xab, 0xde) c('red', 0xff)
def parse_colors(args: ArgsType) -> Dict[str, Optional[int]]: ans: Dict[str, Optional[int]] = {} for spec in args: key, val = spec.split('=', 1) key = key.lower() if key.lower() not in valid_color_names: raise KeyError(f'{key} is not a valid color name') if val.lower() == 'none': col: Optional[int] = None else: q = to_color(val, validate=True) if q is not None: col = int(q) ans[key.lower()] = col return ans
def c(spec, r=0, g=0, b=0): self.ae(tuple(to_color(spec)), (r, g, b))
def main(args: List[str] = sys.argv) -> None: global can_transfer_with_files cli_opts, items_ = parse_args(args[1:], options_spec, usage, help_text, f'{appname} +kitten icat', result_class=IcatCLIOptions) items: List[Union[str, bytes]] = list(items_) if cli_opts.print_window_size: screen_size_function.cache_clear() with open(os.ctermid()) as tty: try: fd = tty.fileno() except AttributeError: # use default value for fd if ctermid is not available fd = None ss = screen_size_function(fd)() print(f'{ss.width}x{ss.height}', end='') raise SystemExit(0) if not sys.stdout.isatty(): sys.stdout = open(os.ctermid(), 'w') stdin_data = None if cli_opts.stdin == 'yes' or (cli_opts.stdin == 'detect' and sys.stdin is not None and not sys.stdin.isatty()): stdin_data = sys.stdin.buffer.read() if stdin_data: items.insert(0, stdin_data) sys.stdin.close() sys.stdin = open(os.ctermid()) screen_size = get_screen_size_function() signal.signal(signal.SIGWINCH, lambda signum, frame: setattr(screen_size, 'changed', True)) if screen_size().width == 0: if cli_opts.detect_support: raise SystemExit(1) raise SystemExit( 'Terminal does not support reporting screen sizes via the TIOCGWINSZ ioctl' ) parsed_opts = ParsedOpts() if cli_opts.place: try: parsed_opts.place = parse_place(cli_opts.place) except Exception: raise SystemExit( f'Not a valid place specification: {cli_opts.place}') try: parsed_opts.z_index = parse_z_index(cli_opts.z_index) except Exception: raise SystemExit( f'Not a valid z-index specification: {cli_opts.z_index}') if cli_opts.background != 'none': ra = to_color(cli_opts.background) if ra is None: raise SystemExit( f'Not a valid color specification: {cli_opts.background}') parsed_opts.remove_alpha = ra.as_sharp parsed_opts.flip = cli_opts.mirror in ('both', 'vertical') parsed_opts.flop = cli_opts.mirror in ('both', 'horizontal') if cli_opts.detect_support: if not detect_support(wait_for=cli_opts.detection_timeout, silent=True): raise SystemExit(1) print('file' if can_transfer_with_files else 'stream', end='', file=sys.stderr) return if cli_opts.transfer_mode == 'detect': if not detect_support(wait_for=cli_opts.detection_timeout, silent=cli_opts.silent): raise SystemExit( 'This terminal emulator does not support the graphics protocol, use a terminal emulator such as kitty that does support it' ) else: can_transfer_with_files = cli_opts.transfer_mode == 'file' errors = [] if cli_opts.clear: sys.stdout.write(clear_images_on_screen(delete_data=True)) if not items: return if not items: raise SystemExit('You must specify at least one file to cat') if parsed_opts.place: if len(items) > 1 or (isinstance(items[0], str) and os.path.isdir(items[0])): raise SystemExit( f'The --place option can only be used with a single image, not {items}' ) sys.stdout.buffer.write(b'\0337') # save cursor url_pat = re.compile(r'(?:https?|ftp)://', flags=re.I) def hold_if_needed(exit_code_or_msg: Union[int, str]) -> None: if cli_opts.hold: if isinstance(exit_code_or_msg, str): print(exit_code_or_msg, file=sys.stderr, flush=True) exit_code_or_msg = 1 with open(os.ctermid()) as tty, raw_mode(tty.fileno()): tty.buffer.read(1) raise SystemExit(exit_code_or_msg) for item in items: try: process_single_item(item, cli_opts, parsed_opts, url_pat) except NoImageMagick as e: hold_if_needed(str(e)) except OutdatedImageMagick as e: print(e.detailed_error, file=sys.stderr) hold_if_needed(str(e)) except ConvertFailed as e: hold_if_needed(str(e)) except OpenFailed as e: errors.append(e) if parsed_opts.place: sys.stdout.buffer.write(b'\0338') # restore cursor if errors: for err in errors: print(err, file=sys.stderr) hold_if_needed(1 if errors else 0) raise SystemExit()
def c(spec, r=0, g=0, b=0, a=0): c = to_color(spec) self.ae(c.red, r) self.ae(c.green, g) self.ae(c.blue, b) self.ae(c.alpha, a)