Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using keychains #1190

Closed
Melkor333 opened this issue Jul 20, 2018 · 2 comments
Closed

Using keychains #1190

Melkor333 opened this issue Jul 20, 2018 · 2 comments

Comments

@Melkor333
Copy link
Contributor

What I want is similar to vim where you can enter d 3 w as a chain (one after another) and it will delete 3 words. For qtile i would use it for things like mod o q to open qutebrowser or mod g 1 to switch to the first group.

Since qtile is highly scriptable I'm pretty sure this could be done with some code in the config file, but I'm a python beginner and thus don't know how to do it/where to start. If it isn't all too difficult I would be glad if you point me at the right direction.

@Melkor333
Copy link
Contributor Author

I'm sorry if my comment was a bit impolite!
I was now able to do what I want with a subclass of Key.

Before closing this issue, are you interested in having this added to the qtile repo?

Idk what you prefer, but I could either integrate it into libqtile or add it to the example configs. Otherwise I would create a seperate repository for it.

For those interested in how it looks right now

I Have this subclass to do the logic:

class KeyNode(Key):
  def __init__(self, modifiers, key, children, *commands, ishome=False, **kwds):
      super().__init__(modifiers, key, *commands, lazy.function(self.updateMap()), **kwds)
      if commands:
          self.iscommand = True
      else:
          self.iscommand = False
      self.ishome = ishome
      self.children = children

  def addchildren(self, *children):
      for child in children:
          self.children.append(child)
          if hasattr(self, 'home'):
              child.sethome(self.home)

  def sethome(self, key):
      if not hasattr(self, 'home'):
          self.home = key
      if not self.iscommand:
          for child in self.children:
              child.sethome(self.home)

  def updateMap(self):
      def f(qtile):
          # make a copy of the list because it will change during the loop
          keylist = qtile.keyMap.copy()
          for key in keylist:
              qtile.unmapKey(qtile.keyMap[key])

          if self.iscommand and hasattr(self, 'home'):
              n = self.home
          else:
              n = self

          for child in n.children:
              qtile.mapKey(child)
          if not n.ishome and hasattr(n, 'home'):
              qtile.mapKey(n.home)
      return f

And creating a Keychain looks like this:

home = KeyNode([], "Escape", [], ishome=True)
keys = home.children

alt = KeyNode([], "Alt_L", [])
alt.sethome(home)
home.addchildren(alt)

alt.addchildren(
            KeyNode([], 'o', [
                KeyNode([], 'q', [], lazy.spawn("qutebrowser")),
                KeyNode([], 'x', [], lazy.spawn("xterm")),
            ]),
            KeyNode([], 'h', [], lazy.layout.left()),
            KeyNode([], 'l', [], lazy.layout.right()),
            KeyNode([], 'j', [], lazy.layout.down()),
            KeyNode([], 'k', [], lazy.layout.up()),
)

With this config I can do alt o x to open a terminal or alt l to go the the right layout, etc.
As you can see a new keynode is created almost the same as a normal key, with the difference that it also has a list for children. A key can then be added as a child to another key to be added to the chain.

when integrating into qtile, I would probably create one home key like qtile.home so that this doesn't have to be created in the config itself. And the sethome() could also be run in the background.

@ramnes
Copy link
Member

ramnes commented Nov 10, 2018

Well if there are people that want such a feature, which seems to be the case, then there is a place for it in Qtile!

I'll go ahead and close this issue in favor of #1208, that have seen more activity. Feel free to ping me if for some reason you want to re-open that issue in particular. 👍

Thank you @Melkor333.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants