From 4f135be86c74f769dbf4002c3b53b0138af6c67b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 13 Jan 2020 20:05:50 +0530 Subject: [PATCH] Allow creating markers dynamically --- docs/marks.rst | 13 +++++++++++++ kitty/boss.py | 29 ++++++++++++++++++++++++++--- kitty/marks.py | 18 +++++++++++++++++- kitty/window.py | 27 +++++++++++---------------- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/docs/marks.rst b/docs/marks.rst index fddb9d657..5dd315edd 100644 --- a/docs/marks.rst +++ b/docs/marks.rst @@ -41,6 +41,19 @@ can control the colors used for these groups in :file:`kitty.conf` with:: lines. +Creating markers dynamically +--------------------------------- + +If you want to create markers dynamically rather than pre-defining them in +:file:`kitty.conf` you can do so as follows:: + + map f1 create_marker + map f2 remove_marker + +Then pressing :kbd:`F1` will allow you to enter the marker definition and set +it and pressing :kbd:`F2` will remove the marker. + + The full syntax for creating marks ------------------------------------- diff --git a/kitty/boss.py b/kitty/boss.py index fb15c30dd..00152b934 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -761,9 +761,6 @@ class Boss: args = ['--name=tab-title', '--message', _('Enter the new title for this tab below.'), 'do_set_tab_title', str(tab.id)] self._run_kitten('ask', args) - def show_error(self, title, msg): - self._run_kitten('show_error', args=['--title', title], input_data=msg) - def do_set_tab_title(self, title, tab_id): tm = self.active_tab_manager if tm is not None and title: @@ -773,6 +770,32 @@ class Boss: tab.set_title(title) break + def show_error(self, title, msg): + self._run_kitten('show_error', args=['--title', title], input_data=msg) + + def create_marker(self): + w = self.active_window + if w: + spec = None + + def done(data, target_window_id, self): + nonlocal spec + spec = data['response'] + + def done2(target_window_id, self): + w = self.window_id_map.get(target_window_id) + if w is not None and spec: + try: + w.set_marker(spec) + except Exception as err: + self.show_error(_('Invalid marker specification'), str(err)) + + self._run_kitten('ask', [ + '--name=create-marker', '--message', + _('Create marker, for example:\ntext 1 ERROR') + ], + custom_callback=done, action_on_removal=done2) + def kitty_shell(self, window_type): cmd = ['@', kitty_exe(), '@'] if window_type == 'tab': diff --git a/kitty/marks.py b/kitty/marks.py index 620d8c1d0..93accd5b1 100644 --- a/kitty/marks.py +++ b/kitty/marks.py @@ -2,9 +2,11 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2020, Kovid Goyal +import os import re -from ctypes import c_void_p, cast, c_uint, POINTER +from ctypes import POINTER, c_uint, c_void_p, cast +from .constants import config_dir pointer_to_uint = POINTER(c_uint) @@ -75,3 +77,17 @@ def marker_from_function(func): yield return marker + + +def marker_from_spec(ftype, spec, flags): + if ftype == 'regex': + if len(spec) == 1: + return marker_from_regex(spec[0][1], spec[0][0], flags=flags) + return marker_from_multiple_regex(spec, flags=flags) + if ftype == 'function': + import runpy + path = spec + if not os.path.isabs(path): + path = os.path.join(config_dir, path) + return marker_from_function(runpy.run_path(path, run_name='__marker__').marker) + raise ValueError('Unknown marker type: {}'.format(ftype)) diff --git a/kitty/window.py b/kitty/window.py index 7e17e3e65..25796521f 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -12,7 +12,7 @@ from itertools import chain from .config import build_ansi_color_table from .constants import ( - ScreenGeometry, WindowGeometry, appname, config_dir, get_boss, wakeup + ScreenGeometry, WindowGeometry, appname, get_boss, wakeup ) from .fast_data_types import ( BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM, @@ -608,25 +608,20 @@ class Window: self.screen.scroll(SCROLL_FULL, False) def toggle_marker(self, ftype, spec, flags): - from .marks import marker_from_regex, marker_from_function, marker_from_multiple_regex + from .marks import marker_from_spec key = ftype, spec if key == self.current_marker_spec: self.remove_marker() return - if ftype == 'regex': - if len(spec) == 1: - marker = marker_from_regex(spec[0][1], spec[0][0], flags=flags) - else: - marker = marker_from_multiple_regex(spec, flags=flags) - elif ftype == 'function': - import runpy - path = spec - if not os.path.isabs(path): - path = os.path.join(config_dir, path) - marker = marker_from_function(runpy.run_path(path, run_name='__marker__').marker) - else: - raise ValueError('Unknown marker type: {}'.format(ftype)) - self.screen.set_marker(marker) + self.screen.set_marker(marker_from_spec(ftype, spec, flags)) + self.current_marker_spec = key + + def set_marker(self, spec): + from .config import toggle_marker + from .marks import marker_from_spec + func, (ftype, spec, flags) = toggle_marker('toggle_marker', spec) + key = ftype, spec + self.screen.set_marker(marker_from_spec(ftype, spec, flags)) self.current_marker_spec = key def remove_marker(self):