Implement better syntax highlighting for the new map

This commit is contained in:
Kovid Goyal 2023-12-04 11:54:49 +05:30
parent cf6c00cebe
commit 04eafbea9b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 70 additions and 10 deletions

View File

@ -14,12 +14,12 @@ import subprocess
import sys import sys
import time import time
from functools import lru_cache, partial from functools import lru_cache, partial
from typing import Any, Callable, Dict, Iterable, List, Tuple from typing import Any, Callable, Dict, Iterable, Iterator, List, Tuple
from docutils import nodes from docutils import nodes
from docutils.parsers.rst.roles import set_classes from docutils.parsers.rst.roles import set_classes
from pygments.lexer import RegexLexer, bygroups # type: ignore from pygments.lexer import RegexLexer, bygroups # type: ignore
from pygments.token import Comment, Keyword, Literal, Name, Number, String, Whitespace # type: ignore from pygments.token import Comment, Error, Keyword, Literal, Name, Number, String, Whitespace # type: ignore
from sphinx import addnodes, version_info from sphinx import addnodes, version_info
from sphinx.util.logging import getLogger from sphinx.util.logging import getLogger
@ -29,6 +29,7 @@ if kitty_src not in sys.path:
from kitty.conf.types import Definition, expand_opt_references # noqa from kitty.conf.types import Definition, expand_opt_references # noqa
from kitty.constants import str_version, website_url # noqa from kitty.constants import str_version, website_url # noqa
from kitty.fast_data_types import Shlex # noqa
# config {{{ # config {{{
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
@ -345,6 +346,62 @@ class ConfLexer(RegexLexer): # type: ignore
aliases = ['conf'] aliases = ['conf']
filenames = ['*.conf'] filenames = ['*.conf']
def map_flags(self: RegexLexer, val: str, start_pos: int) -> Iterator[Tuple[int, Any, str]]:
expecting_arg = ''
s = Shlex(val)
from kitty.options.utils import allowed_key_map_options
last_pos = 0
while (tok := s.next_word())[0] > -1:
x = tok[1]
if tok[0] > last_pos:
yield start_pos + last_pos, Whitespace, ' ' * (tok[0] - last_pos)
last_pos = tok[0] + len(x)
tok_start = start_pos + tok[0]
if expecting_arg:
yield tok_start, String, x
expecting_arg = ''
elif x.startswith('--'):
expecting_arg = x[2:]
k, sep, v = expecting_arg.partition('=')
k = k.replace('-', '_')
expecting_arg = k
if expecting_arg not in allowed_key_map_options:
yield tok_start, Error, x
elif sep == '=':
expecting_arg = ''
yield tok_start, Name, x
else:
yield tok_start, Name, x
else:
break
def mapargs(self: RegexLexer, match: 're.Match[str]') -> Iterator[Tuple[int, Any, str]]:
start_pos = match.start()
val = match.group()
parts = val.split(maxsplit=1)
if parts[0].startswith('--'):
seen = 0
for (pos, token, text) in self.map_flags(val, start_pos):
yield pos, token, text
seen += len(text)
start_pos += seen
val = val[seen:]
parts = val.split(maxsplit=1)
if not val:
return
yield start_pos, Literal, parts[0] # key spec
if len(parts) == 1:
return
start_pos += len(parts[0])
val = val[len(parts[0]):]
m = re.match(r'(\s+)(\S+)', val)
if m is None:
return
yield start_pos, Whitespace, m.group(1)
yield start_pos + m.start(2), Name.Function, m.group(2) # action function
yield start_pos + m.end(2), String, val[m.end(2):]
tokens = { tokens = {
'root': [ 'root': [
(r'#.*?$', Comment.Single), (r'#.*?$', Comment.Single),
@ -352,7 +409,7 @@ class ConfLexer(RegexLexer): # type: ignore
(r'\s+', Whitespace), (r'\s+', Whitespace),
(r'(include)(\s+)(.+?)$', bygroups(Comment.Preproc, Whitespace, Name.Namespace)), (r'(include)(\s+)(.+?)$', bygroups(Comment.Preproc, Whitespace, Name.Namespace)),
(r'(map)(\s+)', bygroups( (r'(map)(\s+)', bygroups(
Keyword.Declaration, Whitespace), 'args'), Keyword.Declaration, Whitespace), 'mapargs'),
(r'(mouse_map)(\s+)(\S+)(\s+)(\S+)(\s+)(\S+)(\s+)', bygroups( (r'(mouse_map)(\s+)(\S+)(\s+)(\S+)(\s+)(\S+)(\s+)', bygroups(
Keyword.Declaration, Whitespace, String, Whitespace, Name.Variable, Whitespace, String, Whitespace), 'action'), Keyword.Declaration, Whitespace, String, Whitespace, Name.Variable, Whitespace, String, Whitespace), 'action'),
(r'(symbol_map)(\s+)(\S+)(\s+)(.+?)$', bygroups( (r'(symbol_map)(\s+)(\S+)(\s+)(.+?)$', bygroups(
@ -364,6 +421,9 @@ class ConfLexer(RegexLexer): # type: ignore
(r'[a-z_0-9]+$', Name.Function, 'root'), (r'[a-z_0-9]+$', Name.Function, 'root'),
(r'[a-z_0-9]+', Name.Function, 'args'), (r'[a-z_0-9]+', Name.Function, 'args'),
], ],
'mapargs': [
(r'.+$', mapargs, 'root'),
],
'args': [ 'args': [
(r'\s+', Whitespace, 'args'), (r'\s+', Whitespace, 'args'),
(r'\b(yes|no)\b$', Number.Bin, 'root'), (r'\b(yes|no)\b$', Number.Bin, 'root'),

View File

@ -262,7 +262,7 @@ example, lets create a mode to manage windows: switching focus, moving the windo
# Exit the manage window mode # Exit the manage window mode
map --mode mw esc pop_keyboard_mode map --mode mw esc pop_keyboard_mode
Now, if run kitty as: Now, if you run kitty as:
.. code-block:: sh .. code-block:: sh
@ -279,21 +279,21 @@ beeps. This can be controlled by the ``map --on-unknown`` option as shown
below:: below::
# Beep on unknown keys # Beep on unknown keys
map --new-mode XXX --on-unknown beep XXX map --new-mode XXX --on-unknown beep ...
# Ingore unknown keys silently # Ingore unknown keys silently
map --new-mode XXX --on-unknown ignore XXX map --new-mode XXX --on-unknown ignore ...
# Beep and exit the keyboard mode on unknown key # Beep and exit the keyboard mode on unknown key
map --new-mode XXX --on-unknown end XXX map --new-mode XXX --on-unknown end ...
# Pass unknown keys to the program running in the active window # Pass unknown keys to the program running in the active window
map --new-mode XXX --on-unknown passthrough XXX map --new-mode XXX --on-unknown passthrough ...
When a key matches an action in a custom keyboard mode, the action is performed When a key matches an action in a custom keyboard mode, the action is performed
and the custom keyboard mode remains in effect. If you would rather have the and the custom keyboard mode remains in effect. If you would rather have the
keyboard mode end after the action you can use ``map --on-action`` as shown keyboard mode end after the action you can use ``map --on-action`` as shown
below:: below::
# Have this keyboar dmode automatically exit after performing any action # Have this keyboard mode automatically exit after performing any action
map --new-mode XXX --on-action end map --new-mode XXX --on-action end ...
All mappable actions All mappable actions