Allow setting markers using remote control

This commit is contained in:
Kovid Goyal 2020-01-14 15:06:52 +05:30
parent 3593189a75
commit 4dde98305e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 99 additions and 13 deletions

View File

@ -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
-------------------------------------

View File

@ -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',

View File

@ -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):

View File

@ -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
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