Allow setting markers using remote control
This commit is contained in:
parent
3593189a75
commit
4dde98305e
@ -37,7 +37,7 @@ can control the colors used for these groups in :file:`kitty.conf` with::
|
||||
|
||||
.. note::
|
||||
For performance reasons, matching is done per line only, and only when that line is
|
||||
altered in anyway. So you cannot match text that stretches across multiple
|
||||
altered in any way. So you cannot match text that stretches across multiple
|
||||
lines.
|
||||
|
||||
|
||||
@ -53,6 +53,9 @@ If you want to create markers dynamically rather than pre-defining them in
|
||||
Then pressing :kbd:`F1` will allow you to enter the marker definition and set
|
||||
it and pressing :kbd:`F2` will remove the marker.
|
||||
|
||||
You can also use the facilities for :doc:`remote-control` to dynamically
|
||||
add/remove markers.
|
||||
|
||||
|
||||
The full syntax for creating marks
|
||||
-------------------------------------
|
||||
|
||||
@ -381,6 +381,82 @@ def set_tab_title(boss, window, payload):
|
||||
# }}}
|
||||
|
||||
|
||||
# create_marker {{{
|
||||
@cmd(
|
||||
'Create a marker that highlights specified text',
|
||||
'Create a marker which can highlight text in the specified window. For example: '
|
||||
'create_marker text 1 ERROR. For full details see: https://sw.kovidgoyal.net/kitty/marks.html',
|
||||
options_spec=MATCH_WINDOW_OPTION + '''\n
|
||||
--self
|
||||
type=bool-set
|
||||
If specified apply marker to the window this command is run in, rather than the active window.
|
||||
''',
|
||||
argspec='MARKER SPECIFICATION'
|
||||
)
|
||||
def cmd_create_marker(global_opts, opts, args):
|
||||
'''
|
||||
match: Which window to detach
|
||||
self: Boolean indicating whether to detach the window the command is run in
|
||||
marker_spec: A list or arguments that define the marker specification, for example: ['text', '1', 'ERROR']
|
||||
'''
|
||||
from .config import parse_marker_spec
|
||||
if len(args) < 2:
|
||||
raise ValueError('Invalid marker specification: {}'.format(' '.join(args)))
|
||||
parse_marker_spec(args[0], args[1:])
|
||||
return {'match': opts.match, 'self': opts.self, 'marker_spec': args}
|
||||
|
||||
|
||||
def create_marker(boss, window, payload):
|
||||
pg = cmd_create_marker.payload_get
|
||||
match = pg(payload, 'match')
|
||||
if match:
|
||||
windows = tuple(boss.match_windows(match))
|
||||
if not windows:
|
||||
raise MatchError(match)
|
||||
else:
|
||||
windows = [window if window and pg(payload, 'self') else boss.active_window]
|
||||
args = pg(payload, 'marker_spec')
|
||||
|
||||
for window in windows:
|
||||
window.set_marker(args)
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# remove_marker {{{
|
||||
@cmd(
|
||||
'Remove the currently set marker, if any.',
|
||||
options_spec=MATCH_WINDOW_OPTION + '''\n
|
||||
--self
|
||||
type=bool-set
|
||||
If specified apply marker to the window this command is run in, rather than the active window.
|
||||
''',
|
||||
argspec=''
|
||||
)
|
||||
def cmd_remove_marker(global_opts, opts, args):
|
||||
'''
|
||||
match: Which window to detach
|
||||
self: Boolean indicating whether to detach the window the command is run in
|
||||
'''
|
||||
return {'match': opts.match, 'self': opts.self}
|
||||
|
||||
|
||||
def remove_marker(boss, window, payload):
|
||||
pg = cmd_create_marker.payload_get
|
||||
match = pg(payload, 'match')
|
||||
if match:
|
||||
windows = tuple(boss.match_windows(match))
|
||||
if not windows:
|
||||
raise MatchError(match)
|
||||
else:
|
||||
windows = [window if window and pg(payload, 'self') else boss.active_window]
|
||||
|
||||
for window in windows:
|
||||
window.remove_marker()
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# detach_window {{{
|
||||
@cmd(
|
||||
'Detach a window and place it in a different/new tab',
|
||||
|
||||
@ -241,19 +241,13 @@ def disable_ligatures_in(func, rest):
|
||||
return func, [where, strategy]
|
||||
|
||||
|
||||
@func_with_args('toggle_marker')
|
||||
def toggle_marker(func, rest):
|
||||
parts = rest.split(maxsplit=1)
|
||||
if len(parts) != 2:
|
||||
raise ValueError('{} if not a valid marker specification'.format(rest))
|
||||
ftype, spec = parts
|
||||
def parse_marker_spec(ftype, parts):
|
||||
flags = re.UNICODE
|
||||
if ftype in ('text', 'itext', 'regex', 'iregex'):
|
||||
parts = spec.split()
|
||||
if ftype.startswith('i'):
|
||||
flags |= re.IGNORECASE
|
||||
if not parts or len(parts) % 2 != 0:
|
||||
raise ValueError('No color specified in marker: {}'.format(spec))
|
||||
raise ValueError('No color specified in marker: {}'.format(' '.join(parts)))
|
||||
ans = []
|
||||
for i in range(0, len(parts), 2):
|
||||
try:
|
||||
@ -267,10 +261,20 @@ def toggle_marker(func, rest):
|
||||
ftype = 'regex'
|
||||
spec = tuple(ans)
|
||||
elif ftype == 'function':
|
||||
pass
|
||||
spec = ' '.join(parts)
|
||||
else:
|
||||
raise ValueError('Unknown marker type: {}'.format(ftype))
|
||||
return func, [ftype, spec, flags]
|
||||
return ftype, spec, flags
|
||||
|
||||
|
||||
@func_with_args('toggle_marker')
|
||||
def toggle_marker(func, rest):
|
||||
parts = rest.split(maxsplit=1)
|
||||
if len(parts) != 2:
|
||||
raise ValueError('{} if not a valid marker specification'.format(rest))
|
||||
ftype, spec = parts
|
||||
parts = spec.split()
|
||||
return func, list(parse_marker_spec(ftype, parts))
|
||||
|
||||
|
||||
def parse_key_action(action):
|
||||
|
||||
@ -617,9 +617,12 @@ class Window:
|
||||
self.current_marker_spec = key
|
||||
|
||||
def set_marker(self, spec):
|
||||
from .config import toggle_marker
|
||||
from .config import toggle_marker, parse_marker_spec
|
||||
from .marks import marker_from_spec
|
||||
func, (ftype, spec, flags) = toggle_marker('toggle_marker', spec)
|
||||
if isinstance(spec, str):
|
||||
func, (ftype, spec, flags) = toggle_marker('toggle_marker', spec)
|
||||
else:
|
||||
ftype, spec, flags = parse_marker_spec(spec[0], spec[1:])
|
||||
key = ftype, spec
|
||||
self.screen.set_marker(marker_from_spec(ftype, spec, flags))
|
||||
self.current_marker_spec = key
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user