Browse Source

Introduced Profiles

I've commented out Mirroring keys, as I think the 2nd key causes me to
get a flood of key events (causes unwanted latency for a few seconds)

I'm thinking of refactoring so we only 'keyboard.add_hotkey' instead of
listening to all keys (This should reduce resources, while remaining
almost 100% identical to previous operation, as in usage should remain
unchanged, perhaps doing this will allow me to configure it so it's able
to mirror without unwanted latency)
Apollo 4 months ago
parent
commit
35b9815eb3
4 changed files with 114 additions and 40 deletions
  1. 1 1
      _example/_example.toml
  2. 30 0
      _example/keys/.example_mirror.toml
  3. 17 3
      _example/keys/example.toml
  4. 66 36
      tyrell.py

+ 1 - 1
example_profile.toml → _example/_example.toml

@@ -1,7 +1,7 @@
 
 # Placeholders
 
-# Use '{name}' to emit profile name (the file name)
+# Use '{name}' to emit profile name
 placeholder_name = false
 
 # Default Features

+ 30 - 0
_example/keys/.example_mirror.toml

@@ -0,0 +1,30 @@
+
+# Mirrors are currently disabled, due to unwanted latency
+
+# key to toggle
+keybind = "z"
+
+# kind of event
+kind = "mirror"
+
+# Mirror what key
+mirror = "w"
+
+# When mirror is down, so will this
+# When mirror is up, so will this
+#
+# In this case, shift will be held down when w is (only when toggled on)
+write = "shift"
+
+# Or button could be configured
+#
+# For example: right click when w (down when w is, up when w is)
+#button = "right"
+
+# << REQUIRED >>
+
+# This is needed for "mirror" kinds
+# We don't want delays, so make sure you turn everything off!
+#
+delay = 0
+hold = 0

+ 17 - 3
example.toml → _example/keys/example.toml

@@ -1,5 +1,6 @@
 # Keybind to what key
 # This can be any key, but must be only 1
+# On keybinds with durations or mirrors, this toggles them on and off
 #
 keybind = "h"
 
@@ -8,15 +9,20 @@ keybind = "h"
 # key        ->  Type the following keys (pressing each key)
 # click down ->  Click and never release a mouse button
 # key down   ->  Press the following keys (never releasing them)
+# mirror     ->  When the "mirror" key is pressed fire this keybind also (While the mirror key is down this bind is active, when up bind is inactive)
+#                See also example_mirror.toml
+#
+# mirror is disabled, due to unwanted latency
 #
 kind = "key"
 
 # << Optional >>
 
 # Write this out
-# This is required for 'key' and 'key down' kinds
+# This is required for 'key' and 'key down' kinds (Optional in 'mirror' kinds, should be a single key)
 # Capital letters will automatically include 'shift'
-# TODO: Separate each of these by space (as space should be 'space' rather than ' ', so other keybinds 'ctrl c' can work)
+# TODO: Separate each of these by space (as space should be 'space' rather than ' ', so other keybinds 'ctrl c' for CTRL+C can work)
+#       (It would also then be possible for 'shift' to be a valid keybind output)
 #
 write = "Hello World!" # This works, but uses unexpected/undesired space (See TODO above)
 
@@ -28,11 +34,19 @@ write = "Hello World!" # This works, but uses unexpected/undesired space (See TO
 
 # This is commented out so this example works
 # Use this Button
-# This is required for 'click' and 'click down' kinds
+# This is required for 'click' and 'click down' kinds (Optional in 'mirror' kinds)
 # There is 'left' and 'right'
 #
 #button = "left"
 
+# This is commented out because the example isn't a 'mirror' kind
+# This is the key that will be mirrored (It's down or up states will be mirrored in write or button as defined above)
+# See also example_mirror.toml
+#
+# mirror is disabled, due to unwanted latency
+#
+#mirror = "g"
+
 # << Override >>
 # The below values are set to their defaults
 # These are optional, and only used for this keybind

+ 66 - 36
tyrell.py

@@ -89,12 +89,14 @@ else:
     exit()
 
 class Action():
+    name: str
     kind: str
     extra: Dict
     toggled: bool
     delay: int
     max_delay: int
-    def __init__(self, kind, extra=None, toggled=False, delay=0):
+    def __init__(self, name, kind, extra=None, toggled=False, delay=0):
+        self.name
         self.kind = kind
         self.extra = extra
         self.toggled = toggled
@@ -138,6 +140,7 @@ class Action():
 
 class Tyrell():
     keybinds: Dict[str, Action]
+    #mirrors: Dict[str, str] # mirror key -> key in keybinds
     toggled: bool
     delay: int
     hold: int
@@ -153,12 +156,18 @@ class Tyrell():
         self.name = profile_name
         if profile_name.endswith(".toml"):
             self.name = profile_name.removesuffix(".toml")
-        if exists(self.name+".toml"):
-            with open(self.name+".toml", "r") as f:
+        if not exists(self.name) or not isdir(self.name):
+            print_err(f"Invalid profile '{self.name}'")
+            print_info(f"This should be a directory")
+            exit()
+        profile_config = join(self.name, self.name+".toml")
+        if exists(profile_config):
+            with open(profile_config, "r") as f:
                 try:
                     t = toml_load(f)
                 except Exception as err:
-                    print_err(f"Invalid profile '{self.name+'.toml'}'")
+                    print_err(f"Invalid profile '{self.name}'")
+                    print_info(f"Invalid '{self.name+'.toml'}' config")
                     print(err)
                     exit()
                 self.profile = t
@@ -175,12 +184,28 @@ class Tyrell():
                 if "placeholder_name" not in self.profile:
                     self.profile["placeholder_name"] = False
         else:
-            print_err(f"Invalid profile '{self.name+'.toml'}'")
+            print_err(f"Invalid profile '{self.name}'")
+            print_info(f"Missing '{self.name+'.toml'}' config")
             exit()
         self.delay = self.profile["delay"]
         self.hold = self.profile["hold"]
         self.keybinds = {}
+        #self.mirrors = {}
         self.toggled = False
+        if not exists(join(self.name, 'keys')):
+            print_err(f"Invalid profile '{self.name}'")
+            print_info("Missing 'keys' directory (for keybinds)")
+            exit()
+        else:
+            for ent in listdir(join(self.name, "keys")):
+                if ent.startswith(".") or isdir(ent) or not ent.endswith(".toml"):
+                    continue
+                with open(join(self.name, "keys", ent), "r") as f:
+                    t = toml_load(f)
+                    if "duration" in t:
+                        self.add_action(t["keybind"], Action(ent.removesuffix(".toml"), t["kind"], extra=t, delay=t["duration"]))
+                    else:
+                        self.add_action(t["keybind"], Action(ent.removesuffix(".toml"), t["kind"], extra=t))
 
     def toggle(self, all: bool=False, all_tickers: bool=False, all_notickers: bool=False) -> bool:
         self.toggled = not self.toggled
@@ -239,6 +264,8 @@ class Tyrell():
         if "placeholder_name" in self.profile:
             if self.profile["placeholder_name"] and "write" in act.extra:
                     act.extra["write"] = act.extra["write"].replace("{name}", self.name)
+        if act.kind == "mirror" and "mirror" in act.extra:
+            self.mirrors[act.extra["mirror"]] = bind
         self.keybinds[bind] = act
 
     def remove_action(self, bind: str):
@@ -247,6 +274,19 @@ class Tyrell():
     def is_action(self, bind: str) -> bool:
         return self.keybinds[bind] is not None
 
+    def print_help(self):
+        print_ok(f"{int(1000 / self.profile['tick'])} ticks per second ({self.profile['tick']} ms per tick)")
+        print_ok(f"Name placeholder: {self.profile['placeholder_name']}")
+        print_warn(f"{self.profile['activator']} -> Activate/Deactivate")
+        print_warn(f"{self.profile['helper']} -> Displays Help")
+        for key in self.keybinds:
+            act = self.keybinds[key]
+            if act.max_delay == 0 and act.toggled:
+                print_info(f"{key} -> {act.name}")
+            else:
+                print_info(f"{key} -> {act.name} = {act.toggled} ({act.delay} ticks)")
+        print_ok("Please use " + style("CTRL+C", fg="bright_yellow") + " to stop")
+
     def tick(self):
         for key in self.keybinds:
             act = self.keybinds[key]
@@ -255,6 +295,21 @@ class Tyrell():
 
     def callback(self, event: KeyboardEvent):
         key_name = event.name
+        #if key_name in self.mirrors:
+        #    # key mirrors currently lag
+        #    act = self.keybinds[self.mirrors[key_name]]
+        #    if act.toggled:
+        #        if "write" in act.extra:
+        #            if event.event_type == "down":
+        #                key_down(act.extra["write"])
+        #            else:
+        #                key_up(act.extra["write"])
+        #        elif "button" in act.extra:
+        #            if event.event_type == "down":
+        #                mouse_down(button=act.extra["button"])
+        #            else:
+        #                mouse_up(button=act.extra["button"])
+        #if event.event_type == "up":
         if key_name == self.profile["activator"]:
             if self.toggle():
                 print_ok("ON")
@@ -265,17 +320,7 @@ class Tyrell():
             #print(f"Code:      {event.scan_code}")
             #print(f"Modifiers: {event.modifiers}")
             if self.profile["helper"] == "?" and "shift" in event.modifiers and event.name == "/" or key_name == self.profile["helper"]:
-                print_ok(f"{int(1000 / self.profile['tick'])} ticks per second ({self.profile['tick']} ms per tick)")
-                print_ok(f"Name placeholder: {self.profile['placeholder_name']}")
-                print_warn(f"{self.profile["activator"]} -> Activate/Deactivate")
-                print_warn(f"{self.profile["helper"]} -> Displays Help")
-                for key in self.keybinds:
-                    act = self.keybinds[key]
-                    if act.max_delay == 0 and act.toggled:
-                        print_info(f"{key} -> {act.kind}")
-                    else:
-                        print_info(f"{key} -> {act.kind} = {act.toggled}")
-                print_ok("Please use " + style("CTRL+C", fg="bright_yellow") + " to stop")
+                self.print_help()
             elif key_name in self.keybinds:
                 act = self.keybinds[key_name]
                 if act.max_delay == 0 and act.toggled:
@@ -307,32 +352,17 @@ if __name__ == "__main__":
         print()
         exit()
     ty = Tyrell(",".join(argv[1:]))
-    if not exists("keys"):
-        print_err("Missing 'keys' directory")
-        print_info("(Might want some keybinds)")
-        exit()
-    print_ok(f"{int(1000 / ty.profile['tick'])} ticks per second ({ty.profile['tick']} ms per tick)")
-    print_ok(f"Name placeholder: {ty.profile['placeholder_name']}")
-    print_warn(f"{ty.profile["activator"]} -> Activate/Deactivate")
-    print_warn(f"{ty.profile["helper"]} -> Displays Help")
-    for ent in listdir("keys"):
-        if ent.startswith(".") or not ent.endswith(".toml") or isdir(ent):
-            continue
-        with open(join("keys", ent), "r") as f:
-            t = toml_load(f)
-            if "duration" in t:
-                ty.add_action(t["keybind"], Action(t["kind"], extra=t, delay=t["duration"]))
-            else:
-                ty.add_action(t["keybind"], Action(t["kind"], extra=t))
-            print_info(f"{t['keybind']} -> {t['kind']}")
     if len(ty.keybinds) == 0:
         print_err("Missing keybinds")
         print_info("(Might want some keybinds, place them in a 'keys' directory)")
-        print_info("(  Need an example? Look at 'example.toml')")
+        print_info(f"(  Need an example? Look at '{join('_example', 'keys', 'example.toml')}')")
         exit()
     ty.enable(all_notickers=True)
     ty.disable()
-    print_ok("Please use " + style("CTRL+C", fg="bright_yellow") + " to stop")
+    ty.print_help()
+    if ty.name == "_example":
+        print_warn("This is the " + style("example", fg="bright_yellow") + ", please define you're own profile")
+        print_info("Please DO NOT EDIT this example profile")
     try:
         run(ty.mainloop())
     except KeyboardInterrupt: