Skip to content

Commit

Permalink
✨ Support --convert
Browse files Browse the repository at this point in the history
  • Loading branch information
Freed-Wu committed Dec 3, 2023
1 parent 237dabd commit ef82233
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 30 deletions.
9 changes: 9 additions & 0 deletions src/zathura_language_server/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ def main():

if args.generate_schema or args.check or args.convert:
from tree_sitter_lsp.utils import pprint
from tree_sitter_zathurarc import parser

from .schema import ZathurarcTrie

if args.generate_schema:
from .misc import get_schema
Expand All @@ -85,6 +88,12 @@ def main():
filetype=args.output_format,
indent=args.indent,
)
for file in args.convert:
pprint(
ZathurarcTrie.from_file(file, parser.parse).to_json(),
filetype=args.output_format,
indent=args.indent,
)
exit(0)

from .server import ZathuraLanguageServer
Expand Down
100 changes: 70 additions & 30 deletions src/zathura_language_server/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
==========
"""
from dataclasses import dataclass
from typing import Literal

from lsprotocol.types import Position, Range
from tree_sitter import Node
Expand All @@ -14,28 +13,7 @@
class ZathurarcTrie(Trie):
r"""Zathurarc Trie."""

value: dict[str, "Trie"] | list["Trie"] | str | Literal[0] = 0

@classmethod
def from_string_node(cls, node: Node, parent: "Trie | None") -> "Trie":
r"""From string node.
:param cls:
:param node:
:type node: Node
:param parent:
:type parent: Trie | None
:rtype: "Trie"
"""
if node.type == "string" and node.children == 3:
node = node.children[1]
text = UNI.node2text(node)
_range = UNI.node2range(node)
if node.type in {"string", "raw_string"} and node.children != 3:
text = text.strip("'\"")
_range.start.character += 1
_range.end.character -= 1
return cls(_range, parent, text)
value: dict[str, "Trie"] | list["Trie"] | str | int | float | bool | None

@classmethod
def from_node(cls, node: Node, parent: "Trie | None") -> "Trie":
Expand All @@ -47,34 +25,96 @@ def from_node(cls, node: Node, parent: "Trie | None") -> "Trie":
:type parent: Trie | None
:rtype: "Trie"
"""
# if node.type == "set_directive":
# node = node.children[1]
# return cls(UNI.node2range(node), parent, node.children[2])
if node.type == "set_directive":
node = node.children[2]
_type = node.type
if _type == "int":
convert = int
elif _type == "float":
convert = float
elif _type == "bool":
convert = bool
else:
convert = lambda x: x.strip("'\"")
return cls(
UNI.node2range(node), parent, convert(UNI.node2text(node))
)
if node.type == "map_directive":
trie = cls(UNI.node2range(node), parent, {})
value: dict[str, Trie] = trie.value # type: ignore
key: Node = node.children[1]
if key.type == "mode":
key: Node = key.next_sibling # type: ignore
shortcut: Node = key.next_sibling # type: ignore
argument = shortcut.next_sibling
value[UNI.node2text(key)] = cls(UNI.node2range(shortcut), trie, {}) # type: ignore
subtrie = value[UNI.node2text(key)] # type: ignore
subvalue: dict[str, Trie] = subtrie.value # type: ignore
subvalue[UNI.node2text(shortcut)] = cls(
UNI.node2range(argument)
if argument
else UNI.node2range(shortcut),
subtrie,
UNI.node2text(argument) if argument else None,
)
return trie
if node.type == "unmap_directive":
key = node.children[1]
if key.type == "mode":
key = key.next_sibling # type: ignore
return cls(UNI.node2range(key), parent, UNI.node2text(key))
if node.type == "file":
trie = cls(Range(Position(0, 0), Position(1, 0)), parent, {})
directives = {
"set_directive",
"map_directive",
"unmap_directive",
"include_directive",
}
for directive in directives:
_type = directive.split("_")[0]
trie.value[_type] = cls( # type: ignore
Range(Position(0, 0), Position(1, 0)), trie, {}
Range(Position(0, 0), Position(1, 0)),
trie,
{} if directive != "include_directive" else [],
)
for child in node.children:
if child.type not in directives:
continue
subtrie: Trie = trie.value[child.type.split("_")[0]] # type: ignore
value: dict[str, Trie] = subtrie.value # type: ignore
value: dict[str, Trie] | list[Trie] = subtrie.value # type: ignore
if child.type == "set_directive":
value: dict[str, Trie]
value[UNI.node2text(child.children[1])] = cls.from_node(
child, subtrie
)
elif child.type == "include_directive":
value += [ # type: ignore
cls(
UNI.node2range(child.children[1]),
subtrie,
UNI.node2text(child.children[1]),
)
]
else:
mode = "normal"
if child.children[1].type == "mode":
mode = child.children[1]
value[mode] = cls.from_node(child, subtrie) # type: ignore
mode = (
UNI.node2text(child.children[1])
.lstrip("[")
.rstrip("]")
)
if mode not in value:
value[mode] = cls(
Range(Position(0, 0), Position(1, 0)),
subtrie,
[],
)
if child.type == "unmap_directive":
value[mode].value += [ # type: ignore
cls.from_node(child, value[mode])
]
else:
value[mode].value += [cls.from_node(child, value[mode])] # type: ignore
return trie
raise NotImplementedError(node.type)
3 changes: 3 additions & 0 deletions tests/zathurarc
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# test
include desktop/zathurarc
map [normal] <Esc> zoom in#with argument
include laptop/zathurarc
map <F1> recolor #without argument
set recolor false
set font 'JetBrainsMono Nerd Font regular 20'
set notification-error-bg "#fbf1c7" # bg
unmap <F1>
unmap [normal] <Esc>

0 comments on commit ef82233

Please sign in to comment.