forked from Shinonome/dots-hyprland
cheatsheet
This commit is contained in:
@@ -0,0 +1,232 @@
|
|||||||
|
import "root:/"
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/modules/common"
|
||||||
|
import "root:/modules/common/widgets"
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
|
Scope { // Scope
|
||||||
|
id: root
|
||||||
|
|
||||||
|
Variants { // Window repeater
|
||||||
|
id: cheatsheetVariants
|
||||||
|
model: Quickshell.screens
|
||||||
|
|
||||||
|
PanelWindow { // Window
|
||||||
|
id: cheatsheetRoot
|
||||||
|
visible: false
|
||||||
|
focusable: true
|
||||||
|
|
||||||
|
property var modelData
|
||||||
|
|
||||||
|
screen: modelData
|
||||||
|
exclusiveZone: 0
|
||||||
|
implicitWidth: cheatsheetBackground.width + Appearance.sizes.elevationMargin * 2
|
||||||
|
implicitHeight: cheatsheetBackground.height + Appearance.sizes.elevationMargin * 2
|
||||||
|
WlrLayershell.namespace: "quickshell:cheatsheet"
|
||||||
|
// Hyprland 0.49: Focus is always exclusive and setting this breaks mouse focus grab
|
||||||
|
// WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
mask: Region {
|
||||||
|
item: cheatsheetBackground
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprlandFocusGrab { // Click outside to close
|
||||||
|
id: grab
|
||||||
|
windows: [ cheatsheetRoot ]
|
||||||
|
active: false
|
||||||
|
onCleared: () => {
|
||||||
|
if (!active) cheatsheetRoot.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: cheatsheetRoot
|
||||||
|
function onVisibleChanged() {
|
||||||
|
delayedGrabTimer.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: delayedGrabTimer
|
||||||
|
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
|
||||||
|
repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
grab.active = cheatsheetRoot.visible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Background
|
||||||
|
Rectangle {
|
||||||
|
id: cheatsheetBackground
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: Appearance.colors.colLayer0
|
||||||
|
radius: Appearance.rounding.windowRounding
|
||||||
|
property real padding: 30
|
||||||
|
implicitWidth: cheatsheetColumnLayout.implicitWidth + padding * 2
|
||||||
|
implicitHeight: cheatsheetColumnLayout.implicitHeight + padding * 2
|
||||||
|
|
||||||
|
Keys.onPressed: (event) => { // Esc to close
|
||||||
|
if (event.key === Qt.Key_Escape) {
|
||||||
|
cheatsheetRoot.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button { // Close button
|
||||||
|
id: closeButton
|
||||||
|
focus: cheatsheetRoot.visible
|
||||||
|
implicitWidth: 40
|
||||||
|
implicitHeight: 40
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
right: parent.right
|
||||||
|
topMargin: 20
|
||||||
|
rightMargin: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
PointingHandInteraction {}
|
||||||
|
onClicked: {
|
||||||
|
cheatsheetRoot.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Item {}
|
||||||
|
contentItem: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
color: closeButton.pressed ? Appearance.colors.colLayer0Active :
|
||||||
|
closeButton.hovered ? Appearance.colors.colLayer0Hover :
|
||||||
|
Appearance.transparentize(Appearance.colors.colLayer0, 1)
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Appearance.animation.elementMoveFast.duration
|
||||||
|
easing.type: Appearance.animation.elementMoveFast.type
|
||||||
|
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialSymbol {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.title
|
||||||
|
text: "close"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout { // Real content
|
||||||
|
id: cheatsheetColumnLayout
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: 20
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: cheatsheetTitle
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
font.family: Appearance.font.family.title
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.title
|
||||||
|
text: qsTr("Cheat sheet")
|
||||||
|
}
|
||||||
|
CheatsheetKeybinds {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shadow
|
||||||
|
DropShadow {
|
||||||
|
anchors.fill: cheatsheetBackground
|
||||||
|
horizontalOffset: 0
|
||||||
|
verticalOffset: 2
|
||||||
|
radius: Appearance.sizes.elevationMargin
|
||||||
|
samples: Appearance.sizes.elevationMargin * 2 + 1 // Ideally should be 2 * radius + 1, see qt docs
|
||||||
|
color: Appearance.colors.colShadow
|
||||||
|
source: cheatsheetBackground
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
target: "cheatsheet"
|
||||||
|
|
||||||
|
function toggle(): void {
|
||||||
|
for (let i = 0; i < cheatsheetVariants.instances.length; i++) {
|
||||||
|
let panelWindow = cheatsheetVariants.instances[i];
|
||||||
|
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
|
||||||
|
panelWindow.visible = !panelWindow.visible;
|
||||||
|
if(panelWindow.visible) Notifications.timeoutAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(): void {
|
||||||
|
for (let i = 0; i < cheatsheetVariants.instances.length; i++) {
|
||||||
|
let panelWindow = cheatsheetVariants.instances[i];
|
||||||
|
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
|
||||||
|
panelWindow.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function open(): void {
|
||||||
|
for (let i = 0; i < cheatsheetVariants.instances.length; i++) {
|
||||||
|
let panelWindow = cheatsheetVariants.instances[i];
|
||||||
|
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
|
||||||
|
panelWindow.visible = true;
|
||||||
|
if(panelWindow.visible) Notifications.timeoutAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "cheatsheetToggle"
|
||||||
|
description: "Toggles cheatsheet on press"
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
for (let i = 0; i < cheatsheetVariants.instances.length; i++) {
|
||||||
|
let panelWindow = cheatsheetVariants.instances[i];
|
||||||
|
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
|
||||||
|
panelWindow.visible = !panelWindow.visible;
|
||||||
|
if(panelWindow.visible) Notifications.timeoutAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "cheatsheetOpen"
|
||||||
|
description: "Opens cheatsheet on press"
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
for (let i = 0; i < cheatsheetVariants.instances.length; i++) {
|
||||||
|
let panelWindow = cheatsheetVariants.instances[i];
|
||||||
|
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
|
||||||
|
panelWindow.visible = true;
|
||||||
|
if(panelWindow.visible) Notifications.timeoutAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "cheatsheetClose"
|
||||||
|
description: "Closes cheatsheet on press"
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
for (let i = 0; i < cheatsheetVariants.instances.length; i++) {
|
||||||
|
let panelWindow = cheatsheetVariants.instances[i];
|
||||||
|
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
|
||||||
|
panelWindow.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import "root:/"
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/modules/common"
|
||||||
|
import "root:/modules/common/widgets"
|
||||||
|
import "root:/modules/common/functions/file_utils.js" as FileUtils
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
readonly property var keybinds: HyprlandKeybinds.keybinds
|
||||||
|
property real spacing: 20
|
||||||
|
property real titleSpacing: 7
|
||||||
|
implicitWidth: rowLayout.implicitWidth
|
||||||
|
implicitHeight: rowLayout.implicitHeight
|
||||||
|
|
||||||
|
property var keyBlacklist: ["Super_L"]
|
||||||
|
property var keySubstitutions: ({
|
||||||
|
"Super": "",
|
||||||
|
"mouse_up": "Scroll ↓", // ikr, weird
|
||||||
|
"mouse_down": "Scroll ↑", // trust me bro
|
||||||
|
"mouse:272": "LMB",
|
||||||
|
"mouse:273": "RMB",
|
||||||
|
"mouse:275": "MouseBack",
|
||||||
|
"Slash": "/",
|
||||||
|
"Hash": "#"
|
||||||
|
})
|
||||||
|
|
||||||
|
RowLayout { // Keybind columns
|
||||||
|
id: rowLayout
|
||||||
|
spacing: root.spacing
|
||||||
|
Repeater {
|
||||||
|
model: keybinds.children
|
||||||
|
|
||||||
|
delegate: ColumnLayout { // Keybind sections
|
||||||
|
spacing: root.spacing
|
||||||
|
required property var modelData
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Repeater {
|
||||||
|
model: modelData.children
|
||||||
|
|
||||||
|
delegate: Item { // Section with real keybinds
|
||||||
|
required property var modelData
|
||||||
|
implicitWidth: sectionColumnLayout.implicitWidth
|
||||||
|
implicitHeight: sectionColumnLayout.implicitHeight
|
||||||
|
ColumnLayout {
|
||||||
|
id: sectionColumnLayout
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: root.titleSpacing
|
||||||
|
StyledText {
|
||||||
|
id: sectionTitle
|
||||||
|
font.family: Appearance.font.family.title
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.huge
|
||||||
|
color: Appearance.colors.colOnLayer0
|
||||||
|
text: modelData.name
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: keybindGrid
|
||||||
|
columns: 2
|
||||||
|
Repeater {
|
||||||
|
model: {
|
||||||
|
var result = [];
|
||||||
|
for (var i = 0; i < modelData.keybinds.length; i++) {
|
||||||
|
const keybind = modelData.keybinds[i];
|
||||||
|
result.push({
|
||||||
|
"type": "keys",
|
||||||
|
"mods": keybind.mods,
|
||||||
|
"key": keybind.key,
|
||||||
|
});
|
||||||
|
result.push({
|
||||||
|
"type": "comment",
|
||||||
|
"comment": keybind.comment,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
delegate: Item {
|
||||||
|
required property var modelData
|
||||||
|
implicitWidth: keybindLoader.implicitWidth
|
||||||
|
implicitHeight: keybindLoader.implicitHeight
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: keybindLoader
|
||||||
|
sourceComponent: (modelData.type === "keys") ? keysComponent : commentComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: keysComponent
|
||||||
|
RowLayout {
|
||||||
|
spacing: 4
|
||||||
|
Repeater {
|
||||||
|
model: modelData.mods
|
||||||
|
delegate: KeyboardKey {
|
||||||
|
required property var modelData
|
||||||
|
key: keySubstitutions[modelData] || modelData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: keybindPlus
|
||||||
|
visible: !keyBlacklist.includes(modelData.key) && modelData.mods.length > 0
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
text: "+"
|
||||||
|
}
|
||||||
|
KeyboardKey {
|
||||||
|
id: keybindKey
|
||||||
|
visible: !keyBlacklist.includes(modelData.key)
|
||||||
|
key: keySubstitutions[modelData.key] || modelData.key
|
||||||
|
color: Appearance.colors.colOnLayer0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: commentComponent
|
||||||
|
Item {
|
||||||
|
id: commentItem
|
||||||
|
implicitWidth: commentText.implicitWidth + 5 * 2
|
||||||
|
implicitHeight: commentText.implicitHeight
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: commentText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||||
|
text: modelData.comment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -108,8 +108,8 @@ Singleton {
|
|||||||
property color colSubtext: m3colors.m3outline
|
property color colSubtext: m3colors.m3outline
|
||||||
property color colLayer0: m3colors.m3background
|
property color colLayer0: m3colors.m3background
|
||||||
property color colOnLayer0: m3colors.m3onBackground
|
property color colOnLayer0: m3colors.m3onBackground
|
||||||
property color colLayer0Hover: mix(colLayer0, colOnLayer0, 0.85)
|
property color colLayer0Hover: mix(colLayer0, colOnLayer0, 0.9)
|
||||||
property color colLayer0Active: m3colors.m3surfaceContainerHigh
|
property color colLayer0Active: mix(colLayer0, colOnLayer0, 0.8)
|
||||||
property color colLayer1: m3colors.m3surfaceContainerLow;
|
property color colLayer1: m3colors.m3surfaceContainerLow;
|
||||||
property color colOnLayer1: m3colors.m3onSurfaceVariant;
|
property color colOnLayer1: m3colors.m3onSurfaceVariant;
|
||||||
property color colOnLayer1Inactive: mix(colOnLayer1, colLayer1, 0.45);
|
property color colOnLayer1Inactive: mix(colOnLayer1, colLayer1, 0.45);
|
||||||
@@ -155,7 +155,7 @@ Singleton {
|
|||||||
font: QtObject {
|
font: QtObject {
|
||||||
property QtObject family: QtObject {
|
property QtObject family: QtObject {
|
||||||
property string main: "Rubik"
|
property string main: "Rubik"
|
||||||
property string title: "Rubik"
|
property string title: "Gabarito"
|
||||||
property string iconMaterial: "Material Symbols Rounded"
|
property string iconMaterial: "Material Symbols Rounded"
|
||||||
property string iconNerd: "SpaceMono NF"
|
property string iconNerd: "SpaceMono NF"
|
||||||
property string monospace: "JetBrains Mono NF"
|
property string monospace: "JetBrains Mono NF"
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import "root:/modules/common"
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
property string key
|
||||||
|
|
||||||
|
property real horizontalPadding: 7
|
||||||
|
property real verticalPadding: 2
|
||||||
|
property real borderWidth: 1
|
||||||
|
property real bottomBorderWidth: 3
|
||||||
|
property color borderColor: Appearance.colors.colOnLayer0
|
||||||
|
property real borderRadius: 5
|
||||||
|
property color keyColor: Appearance.m3colors.m3surfaceContainerLow
|
||||||
|
implicitWidth: keyFace.implicitWidth + borderWidth * 2
|
||||||
|
implicitHeight: keyFace.implicitHeight + borderWidth * 2 + bottomBorderWidth
|
||||||
|
radius: borderRadius
|
||||||
|
color: borderColor
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: keyFace
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: borderWidth
|
||||||
|
implicitWidth: keyText.implicitWidth + horizontalPadding * 2
|
||||||
|
implicitHeight: keyText.implicitHeight + verticalPadding * 2
|
||||||
|
color: keyColor
|
||||||
|
radius: borderRadius - borderWidth
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: keyText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.family: Appearance.font.family.monospace
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||||
|
text: key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+222
@@ -0,0 +1,222 @@
|
|||||||
|
#!/usr/bin/env -S\_/bin/sh\_-c\_"source\_\$(eval\_echo\_\$ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate&&exec\_python\_-E\_"\$0"\_"\$@""
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
from os.path import expandvars as os_expandvars
|
||||||
|
from typing import Dict, List
|
||||||
|
|
||||||
|
TITLE_REGEX = "#+!"
|
||||||
|
HIDE_COMMENT = "[hidden]"
|
||||||
|
MOD_SEPARATORS = ['+', ' ']
|
||||||
|
COMMENT_BIND_PATTERN = "#/#"
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Hyprland keybind reader')
|
||||||
|
parser.add_argument('--path', type=str, default="$HOME/.config/hypr/hyprland.conf", help='path to keybind file (sourcing isn\'t supported)')
|
||||||
|
args = parser.parse_args()
|
||||||
|
content_lines = []
|
||||||
|
reading_line = 0
|
||||||
|
|
||||||
|
# Little Parser made for hyprland keybindings conf file
|
||||||
|
Variables: Dict[str, str] = {}
|
||||||
|
|
||||||
|
|
||||||
|
class KeyBinding(dict):
|
||||||
|
def __init__(self, mods, key, dispatcher, params, comment) -> None:
|
||||||
|
self["mods"] = mods
|
||||||
|
self["key"] = key
|
||||||
|
self["dispatcher"] = dispatcher
|
||||||
|
self["params"] = params
|
||||||
|
self["comment"] = comment
|
||||||
|
|
||||||
|
class Section(dict):
|
||||||
|
def __init__(self, children, keybinds, name) -> None:
|
||||||
|
self["children"] = children
|
||||||
|
self["keybinds"] = keybinds
|
||||||
|
self["name"] = name
|
||||||
|
|
||||||
|
|
||||||
|
def read_content(path: str) -> str:
|
||||||
|
if (not os.access(os.path.expanduser(os.path.expandvars(path)), os.R_OK)):
|
||||||
|
return ("error")
|
||||||
|
with open(os.path.expanduser(os.path.expandvars(path)), "r") as file:
|
||||||
|
return file.read()
|
||||||
|
|
||||||
|
|
||||||
|
def autogenerate_comment(dispatcher: str, params: str = "") -> str:
|
||||||
|
match dispatcher:
|
||||||
|
|
||||||
|
case "resizewindow":
|
||||||
|
return "Resize window"
|
||||||
|
|
||||||
|
case "movewindow":
|
||||||
|
if(params == ""):
|
||||||
|
return "Move window"
|
||||||
|
else:
|
||||||
|
return "Window: move in {} direction".format({
|
||||||
|
"l": "left",
|
||||||
|
"r": "right",
|
||||||
|
"u": "up",
|
||||||
|
"d": "down",
|
||||||
|
}.get(params, "null"))
|
||||||
|
|
||||||
|
case "pin":
|
||||||
|
return "Window: pin (show on all workspaces)"
|
||||||
|
|
||||||
|
case "splitratio":
|
||||||
|
return "Window split ratio {}".format(params)
|
||||||
|
|
||||||
|
case "togglefloating":
|
||||||
|
return "Float/unfloat window"
|
||||||
|
|
||||||
|
case "resizeactive":
|
||||||
|
return "Resize window by {}".format(params)
|
||||||
|
|
||||||
|
case "killactive":
|
||||||
|
return "Close window"
|
||||||
|
|
||||||
|
case "fullscreen":
|
||||||
|
return "Toggle {}".format(
|
||||||
|
{
|
||||||
|
"0": "fullscreen",
|
||||||
|
"1": "maximization",
|
||||||
|
"2": "fullscreen on Hyprland's side",
|
||||||
|
}.get(params, "null")
|
||||||
|
)
|
||||||
|
|
||||||
|
case "fakefullscreen":
|
||||||
|
return "Toggle fake fullscreen"
|
||||||
|
|
||||||
|
case "workspace":
|
||||||
|
if params == "+1":
|
||||||
|
return "Workspace: focus right"
|
||||||
|
elif params == "-1":
|
||||||
|
return "Workspace: focus left"
|
||||||
|
return "Focus workspace {}".format(params)
|
||||||
|
|
||||||
|
case "movefocus":
|
||||||
|
return "Window: move focus {}".format(
|
||||||
|
{
|
||||||
|
"l": "left",
|
||||||
|
"r": "right",
|
||||||
|
"u": "up",
|
||||||
|
"d": "down",
|
||||||
|
}.get(params, "null")
|
||||||
|
)
|
||||||
|
|
||||||
|
case "swapwindow":
|
||||||
|
return "Window: swap in {} direction".format(
|
||||||
|
{
|
||||||
|
"l": "left",
|
||||||
|
"r": "right",
|
||||||
|
"u": "up",
|
||||||
|
"d": "down",
|
||||||
|
}.get(params, "null")
|
||||||
|
)
|
||||||
|
|
||||||
|
case "movetoworkspace":
|
||||||
|
if params == "+1":
|
||||||
|
return "Window: move to right workspace (non-silent)"
|
||||||
|
elif params == "-1":
|
||||||
|
return "Window: move to left workspace (non-silent)"
|
||||||
|
return "Window: move to workspace {} (non-silent)".format(params)
|
||||||
|
|
||||||
|
case "movetoworkspacesilent":
|
||||||
|
if params == "+1":
|
||||||
|
return "Window: move to right workspace"
|
||||||
|
elif params == "-1":
|
||||||
|
return "Window: move to right workspace"
|
||||||
|
return "Window: move to workspace {}".format(params)
|
||||||
|
|
||||||
|
case "togglespecialworkspace":
|
||||||
|
return "Workspace: toggle special"
|
||||||
|
|
||||||
|
case "exec":
|
||||||
|
return "Execute: {}".format(params)
|
||||||
|
|
||||||
|
case _:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def get_keybind_at_line(line_number, line_start = 0):
|
||||||
|
global content_lines
|
||||||
|
line = content_lines[line_number]
|
||||||
|
_, keys = line.split("=", 1)
|
||||||
|
keys, *comment = keys.split("#", 1)
|
||||||
|
|
||||||
|
mods, key, dispatcher, *params = list(map(str.strip, keys.split(",", 4)))
|
||||||
|
params = "".join(map(str.strip, params))
|
||||||
|
|
||||||
|
# Remove empty spaces
|
||||||
|
comment = list(map(str.strip, comment))
|
||||||
|
# Add comment if it exists, else generate it
|
||||||
|
if comment:
|
||||||
|
comment = comment[0]
|
||||||
|
if comment.startswith("[hidden]"):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
comment = autogenerate_comment(dispatcher, params)
|
||||||
|
|
||||||
|
if mods:
|
||||||
|
modstring = mods + MOD_SEPARATORS[0] # Add separator at end to ensure last mod is read
|
||||||
|
mods = []
|
||||||
|
p = 0
|
||||||
|
for index, char in enumerate(modstring):
|
||||||
|
if(char in MOD_SEPARATORS):
|
||||||
|
if(index - p > 1):
|
||||||
|
mods.append(modstring[p:index])
|
||||||
|
p = index+1
|
||||||
|
else:
|
||||||
|
mods = []
|
||||||
|
|
||||||
|
return KeyBinding(mods, key, dispatcher, params, comment)
|
||||||
|
|
||||||
|
def get_binds_recursive(current_content, scope):
|
||||||
|
global content_lines
|
||||||
|
global reading_line
|
||||||
|
# print("get_binds_recursive({0}, {1}) [@L{2}]".format(current_content, scope, reading_line + 1))
|
||||||
|
while reading_line < len(content_lines): # TODO: Adjust condition
|
||||||
|
line = content_lines[reading_line]
|
||||||
|
heading_search_result = re.search(TITLE_REGEX, line)
|
||||||
|
# print("Read line {0}: {1}\tisHeading: {2}".format(reading_line + 1, content_lines[reading_line], "[{0}, {1}, {2}]".format(heading_search_result.start(), heading_search_result.start() == 0, ((heading_search_result != None) and (heading_search_result.start() == 0))) if heading_search_result != None else "No"))
|
||||||
|
if ((heading_search_result != None) and (heading_search_result.start() == 0)): # Found title
|
||||||
|
# Determine scope
|
||||||
|
heading_scope = line.find('!')
|
||||||
|
# Lower? Return
|
||||||
|
if(heading_scope <= scope):
|
||||||
|
reading_line -= 1
|
||||||
|
return current_content
|
||||||
|
|
||||||
|
section_name = line[(heading_scope+1):].strip()
|
||||||
|
# print("[[ Found h{0} at line {1} ]] {2}".format(heading_scope, reading_line+1, content_lines[reading_line]))
|
||||||
|
reading_line += 1
|
||||||
|
current_content["children"].append(get_binds_recursive(Section([], [], section_name), heading_scope))
|
||||||
|
|
||||||
|
elif line.startswith(COMMENT_BIND_PATTERN):
|
||||||
|
keybind = get_keybind_at_line(reading_line, line_start=len(COMMENT_BIND_PATTERN))
|
||||||
|
if(keybind != None):
|
||||||
|
current_content["keybinds"].append(keybind)
|
||||||
|
|
||||||
|
elif line == "" or not line.lstrip().startswith("bind"): # Comment, ignore
|
||||||
|
pass
|
||||||
|
|
||||||
|
else: # Normal keybind
|
||||||
|
keybind = get_keybind_at_line(reading_line)
|
||||||
|
if(keybind != None):
|
||||||
|
current_content["keybinds"].append(keybind)
|
||||||
|
|
||||||
|
reading_line += 1
|
||||||
|
|
||||||
|
return current_content;
|
||||||
|
|
||||||
|
def parse_keys(path: str) -> Dict[str, List[KeyBinding]]:
|
||||||
|
global content_lines
|
||||||
|
content_lines = read_content(path).splitlines()
|
||||||
|
if content_lines[0] == "error":
|
||||||
|
return "error"
|
||||||
|
return get_binds_recursive(Section([], [], ""), 0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import json
|
||||||
|
|
||||||
|
ParsedKeys = parse_keys(args.path)
|
||||||
|
print(json.dumps(ParsedKeys))
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import "root:/modules/common"
|
||||||
|
import "root:/modules/common/functions/file_utils.js" as FileUtils
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
property var keybinds: []
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Hyprland
|
||||||
|
|
||||||
|
function onRawEvent(event) {
|
||||||
|
console.log("[CheatsheetKeybinds] Event:", event.name)
|
||||||
|
if (event.name == "configreloaded") {
|
||||||
|
getKeybinds.running = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: getKeybinds
|
||||||
|
running: true
|
||||||
|
command: [FileUtils.trimFileProtocol(`${XdgDirectories.config}/quickshell/scripts/hyprland/get_keybinds.py`),
|
||||||
|
"--path", FileUtils.trimFileProtocol(`${XdgDirectories.config}/hypr/hyprland/keybinds.conf`),]
|
||||||
|
|
||||||
|
stdout: SplitParser {
|
||||||
|
onRead: data => {
|
||||||
|
try {
|
||||||
|
root.keybinds = JSON.parse(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[CheatsheetKeybinds] Error parsing keybinds:", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
//@ pragma UseQApplication
|
//@ pragma UseQApplication
|
||||||
|
|
||||||
import "./modules/bar/"
|
import "./modules/bar/"
|
||||||
|
import "./modules/cheatsheet/"
|
||||||
import "./modules/notificationPopup/"
|
import "./modules/notificationPopup/"
|
||||||
import "./modules/onScreenDisplay/"
|
import "./modules/onScreenDisplay/"
|
||||||
import "./modules/overview/"
|
import "./modules/overview/"
|
||||||
@@ -23,6 +24,7 @@ ShellRoot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bar {}
|
Bar {}
|
||||||
|
Cheatsheet {}
|
||||||
NotificationPopup {}
|
NotificationPopup {}
|
||||||
OnScreenDisplayBrightness {}
|
OnScreenDisplayBrightness {}
|
||||||
OnScreenDisplayVolume {}
|
OnScreenDisplayVolume {}
|
||||||
|
|||||||
Reference in New Issue
Block a user