hyprconf2lua 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,60 @@
1
+ from __future__ import annotations
2
+ from typing import Dict, Optional, Tuple
3
+
4
+ from hyprconf2lua.lexer import tokenize, LexerError
5
+ from hyprconf2lua.parser import parse_config, ParserError
6
+ from hyprconf2lua.codegen import Codegen
7
+
8
+
9
+ class ConversionError(Exception):
10
+ pass
11
+
12
+
13
+ class ConversionResult:
14
+ def __init__(self, lua: str, report: dict, errors: list, warnings: list):
15
+ self.lua = lua
16
+ self.report = report
17
+ self.errors = errors
18
+ self.warnings = warnings
19
+
20
+ @property
21
+ def success(self) -> bool:
22
+ return len(self.errors) == 0
23
+
24
+ @property
25
+ def coverage(self) -> float:
26
+ total = self.report.get("translated", 0) + self.report.get("passthrough", 0) + self.report.get("flagged", 0)
27
+ if total == 0:
28
+ return 100.0
29
+ return round(self.report.get("translated", 0) / total * 100, 1)
30
+
31
+
32
+ def convert(source: str) -> ConversionResult:
33
+ errors: list = []
34
+ warnings: list = []
35
+
36
+ try:
37
+ tokens = tokenize(source)
38
+ except LexerError as e:
39
+ errors.append(str(e))
40
+ return ConversionResult("", {"translated": 0, "passthrough": 0, "flagged": 0}, errors, warnings)
41
+
42
+ try:
43
+ config = parse_config(source)
44
+ except ParserError as e:
45
+ errors.append(str(e))
46
+ return ConversionResult("", {"translated": 0, "passthrough": 0, "flagged": 0}, errors, warnings)
47
+
48
+ gen = Codegen()
49
+ try:
50
+ lua = gen.generate(config)
51
+ except Exception as e:
52
+ errors.append(f"Code generation error: {e}")
53
+ return ConversionResult("", {"translated": 0, "passthrough": 0, "flagged": 0}, errors, warnings)
54
+
55
+ report = gen.get_report()
56
+
57
+ if report["flagged"] > 0:
58
+ warnings.append(f"{report['flagged']} directive(s) flagged for manual review")
59
+
60
+ return ConversionResult(lua, report, errors, warnings)
hyprconf2lua/lexer.py ADDED
@@ -0,0 +1,74 @@
1
+ from __future__ import annotations
2
+ import re
3
+ from dataclasses import dataclass, field
4
+ from typing import List
5
+
6
+
7
+ TOKEN_SPECS = [
8
+ ("COMMENT", r"#[^\n]*"),
9
+ ("BLOCK_OPEN", r"\{"),
10
+ ("BLOCK_CLOSE", r"\}"),
11
+ ("EQUALS", r"="),
12
+ ("COMMA", r","),
13
+ ("DOT", r"\."),
14
+ ("COLON", r":"),
15
+ ("DOLLAR", r"\$"),
16
+ ("STRING", r'"([^"\\]|\\.)*"'),
17
+ ("IDENT", r'[^\s#"={},:!]+'),
18
+ ("NEWLINE", r"\n"),
19
+ ("SKIP", r"[ \t]+"),
20
+ ("MISMATCH", r"."),
21
+ ]
22
+
23
+
24
+ @dataclass
25
+ class Token:
26
+ type: str
27
+ value: str
28
+ line: int
29
+ col: int
30
+
31
+ def __repr__(self) -> str:
32
+ return f"Token({self.type}, {self.value!r}, L{self.line}:{self.col})"
33
+
34
+
35
+ TOKEN_REGEX = re.compile("|".join(f"(?P<{name}>{pattern})" for name, pattern in TOKEN_SPECS))
36
+
37
+
38
+ class LexerError(Exception):
39
+ def __init__(self, message: str, line: int, col: int):
40
+ self.line = line
41
+ self.col = col
42
+ super().__init__(f"L{line}:{col}: {message}")
43
+
44
+
45
+ def tokenize(source: str) -> List[Token]:
46
+ tokens: List[Token] = []
47
+ line = 1
48
+ last_line_start = 0
49
+
50
+ def _col(pos: int) -> int:
51
+ return pos - last_line_start + 1
52
+
53
+ for m in TOKEN_REGEX.finditer(source):
54
+ kind = m.lastgroup
55
+ value = m.group()
56
+ pos = m.start()
57
+
58
+ if kind == "NEWLINE":
59
+ line += 1
60
+ last_line_start = pos + 1
61
+ tokens.append(Token("NEWLINE", value, line - 1, _col(pos)))
62
+ elif kind == "SKIP":
63
+ pass
64
+ elif kind == "COMMENT":
65
+ tokens.append(Token("COMMENT", value, line, _col(pos)))
66
+ elif kind == "MISMATCH":
67
+ raise LexerError(f"Unexpected character: {value!r}", line, _col(pos))
68
+ elif kind == "STRING":
69
+ tokens.append(Token("STRING", value[1:-1], line, _col(pos)))
70
+ else:
71
+ tokens.append(Token(kind, value, line, _col(pos)))
72
+
73
+ tokens.append(Token("EOF", "", line, 1))
74
+ return tokens
@@ -0,0 +1,130 @@
1
+ DISPATCHER_MAP = {
2
+ "exec": ("hl.dsp.exec_cmd", True),
3
+ "execr": ("hl.dsp.exec_raw", True),
4
+ "killactive": ("hl.dsp.window.close", False),
5
+ "kill": ("hl.dsp.window.kill", False),
6
+ "exit": ("hl.dsp.exit", False),
7
+ "fullscreen": ("hl.dsp.window.fullscreen", False),
8
+ "fullscreenstate": ("hl.dsp.window.fullscreen_state", True),
9
+ "togglefloating": ("hl.dsp.window.float", False),
10
+ "setfloating": ("hl.dsp.window.float", True),
11
+ "pseudo": ("hl.dsp.window.pseudo", False),
12
+ "togglesplit": ("hl.dsp.layout", True),
13
+ "layoutmsg": ("hl.dsp.layout", True),
14
+ "cyclenext": ("hl.dsp.window.cycle_next", False),
15
+ "focuswindow": ("hl.dsp.focus", True),
16
+ "focuscurrentorlast":("hl.dsp.focus", True),
17
+ "movefocus": ("hl.dsp.focus", True),
18
+ "movewindow": ("hl.dsp.window.move", True),
19
+ "swapwindow": ("hl.dsp.window.swap", True),
20
+ "swapnext": ("hl.dsp.window.swap", True),
21
+ "centerwindow": ("hl.dsp.window.center", False),
22
+ "resizewindow": ("hl.dsp.window.resize", True),
23
+ "movecursor": ("hl.dsp.cursor.move", True),
24
+ "pin": ("hl.dsp.window.pin", False),
25
+ "tag": ("hl.dsp.window.tag", True),
26
+ "togglegroup": ("hl.dsp.group.toggle", False),
27
+ "changegroupactive": ("hl.dsp.group.next", False),
28
+ "focusgroupwindow": ("hl.dsp.group.active", True),
29
+ "movegroupwindow": ("hl.dsp.group.move_window", True),
30
+ "lockgroups": ("hl.dsp.group.lock", False),
31
+ "workspace": ("hl.dsp.focus", True),
32
+ "movetoworkspace": ("hl.dsp.window.move", True),
33
+ "movetoworkspacesilent": ("hl.dsp.window.move", True),
34
+ "focusmonitor": ("hl.dsp.focus", True),
35
+ "movetomonitor": ("hl.dsp.window.move", True),
36
+ "togglespecialworkspace": ("hl.dsp.workspace.toggle_special", True),
37
+ "renameworkspace": ("hl.dsp.workspace.rename", True),
38
+ "alterzorder": ("hl.dsp.window.alter_zorder", True),
39
+ "setprop": ("hl.dsp.window.set_prop", True),
40
+ "swallows": ("hl.dsp.window.toggle_swallow", False),
41
+ "denywindowfromgroup":("hl.dsp.window.deny_from_group", False),
42
+ "submap": ("hl.dsp.submap", True),
43
+ "pass": ("hl.dsp.pass", True),
44
+ "sendshortcut": ("hl.dsp.send_shortcut", True),
45
+ "dpms": ("hl.dsp.dpms", True),
46
+ "noop": ("hl.dsp.no_op", False),
47
+ "event": ("hl.dsp.event", True),
48
+ "global": ("hl.dsp.global", True),
49
+ "forceidle": ("hl.dsp.force_idle", True),
50
+ "moveintogroup": ("hl.dsp.window.move", True),
51
+ "moveoutofgroup": ("hl.dsp.window.move", True),
52
+ "focusurgentorlast": ("hl.dsp.focus", True),
53
+ "focusonemonitor": ("hl.dsp.focus", True),
54
+ }
55
+
56
+ BIND_FLAGS_TO_OPTIONS = {
57
+ "l": ("locked", "true"),
58
+ "r": ("repeating", "true"),
59
+ "n": ("non_consuming", "true"),
60
+ "m": ("mouse", "true"),
61
+ "e": ("empty", "true"),
62
+ "t": ("transparent", "true"),
63
+ "i": ("ignore_mods", "true"),
64
+ "p": ("pass", "true"),
65
+ }
66
+
67
+ WINDOW_RULE_MAP = {
68
+ "float": ("float", "true"),
69
+ "tile": ("tile", "true"),
70
+ "pin": ("pin", "true"),
71
+ "nofocus": ("no_focus", "true"),
72
+ "noborder": ("border", "false"),
73
+ "noblur": ("blur", "false"),
74
+ "noshadow": ("shadow", "false"),
75
+ "noanim": ("no_anim", "true"),
76
+ "dimaround": ("dim_around", "true"),
77
+ "noblur": ("blur", "false"),
78
+ "noshadow": ("shadow", "false"),
79
+ "nomaxsize": ("max_size", "false"),
80
+ "fakefullscreen": ("fake_fullscreen", "true"),
81
+ "noinitialfocus": ("no_initial_focus", "true"),
82
+ "windowdance": ("window_dance", "true"),
83
+ "nofullscreenrequests": ("suppress_event", "fullscreen"),
84
+ "nomaximizerequest": ("suppress_event", "maximize"),
85
+ }
86
+
87
+ WINDOW_RULE_PARAM_MAP = {
88
+ "opacity": ("opacity", True),
89
+ "alpha": ("alpha", True),
90
+ "border_size": ("border_size", True),
91
+ "rounding": ("rounding", True),
92
+ "monitor": ("monitor", True),
93
+ "workspace": ("workspace", True),
94
+ "move": ("move", True),
95
+ "size": ("size", True),
96
+ "minsize": ("min_size", True),
97
+ "maxsize": ("max_size", True),
98
+ "maxsize": ("max_size", True),
99
+ "idleinhibit": ("idle_inhibit", True),
100
+ "xray": ("xray", True),
101
+ "center": ("center", True),
102
+ "keepaspectratio": ("keep_aspect_ratio", "true"),
103
+ "dimaround": ("dim_around", "true"),
104
+ "fullscreen": ("fullscreen", True),
105
+ "maximize": ("maximize", True),
106
+ "suppressevent": ("suppress_event", True),
107
+ "pseudo": ("pseudo", "true"),
108
+ "stayfocused": ("stay_focused", "true"),
109
+ "group": ("group", True),
110
+ "scroll_touchpad": ("scroll_touchpad", True),
111
+ }
112
+
113
+ WORKSPACE_RULE_MAP = {
114
+ "monitor": "monitor",
115
+ "default": "is_default",
116
+ "gapsin": "gaps_in",
117
+ "gapsout": "gaps_out",
118
+ "bordersize": "border_size",
119
+ "rounding": "rounding",
120
+ "decorate": "decorate",
121
+ "persistent": "persistent",
122
+ }
123
+
124
+ LAYER_RULE_MAP = {
125
+ "blur": ("blur", "true"),
126
+ "ignorealpha": ("ignore_alpha", True),
127
+ "ignorezero": ("ignore_alpha", True),
128
+ "noanim": ("no_anim", "true"),
129
+ "noblur": ("blur", "false"),
130
+ }