13 votes

Y a-t-il un éditeur convivial pour les modifications complexes de Karabiner?

J'ai une longue liste de modifications complexes de Karabiner et il est difficile de les suivre toutes, y compris les conflits, les applications exclues, etc. D'après ce que je peux comprendre, l'utilisateur est censé modifier ~/.config/karabiner/karabiner.json manuellement. Cependant, cela n'est pas du tout pratique, car chaque définition de modification finit par être assez verbeuse et je ne peux voir que 1 à 2 à l'écran. Existe-t-il une méthode plus efficace que j'ignore ? Ou devrais-je simplement écrire mon propre programme pour générer le fichier karabiner.json ?

14voto

Jonne Haß Points 151

Il y a un éditeur web simple ces jours-ci grâce à @genesy: https://genesy.github.io/karabiner-complex-rules-generator/

6voto

Donentolon Points 245

J'ai trouvé Goku (voir réponse de furins) et quelques autres outils mais aucun ne semblait plus facile que de modifier le JSON. Au final, j'ai écrit mes propres scripts que je partagerai ici.

Il y a deux fichiers Python :

  • decompose.py prend un JSON karabiner et le divise en plusieurs fichiers et répertoires, de sorte que vous puissiez éditer une règle à la fois.
  • compose.py prend ces répertoires et les regroupe dans un seul JSON que karabiner acceptera.

Je garde à la fois le JSON unique et les répertoires décomposés (ainsi que le script) dans mon repo de dotfiles. Lorsque je veux modifier un raccourci, je crée un répertoire pour cela (la méthode la plus simple est de copier un existant et de le modifier) puis je fais un encodage/décodage en aller-retour. Ex. : python compose.py; python decompose.py; python compose.py.

Après cela, ma première étape est de vérifier git diff pour voir si ma nouvelle règle comporte une erreur qui a tout cassé. Si c'est le cas, j'ai de nombreuses options pour revenir en arrière via git et réessayer. Une fois terminé, je teste le raccourci avec Karabiner-EventViewer et son cas d'utilisation prévu, puis je commit.

Les scripts sont évidemment limités et bricolés, car ils sont destinés à un usage personnel (et je pense que la "solution" appropriée à cela serait simplement de ne pas utiliser de Mac, har har). Je suggère de commencer avec un JSON connu fonctionnant tel que raccourcis de style PC pour voir comment les règles existantes fonctionnent. Ils fonctionnent raisonnablement bien, mais quelques inconvénients :

  • Chaque règle va dans un répertoire. Le nom du répertoire est construit à partir d'un chiffre (pour éviter que les règles ne changent d'ordre et ne perturbent git) et du nom de la règle. Évidemment les noms de règles peuvent avoir des caractères spéciaux, mais les répertoires non, donc j'ai dû faire une normalisation un peu spéciale avec ça. Cela peut être un peu fragile si vous faites des choses sophistiquées avec le nom de la règle.
  • J'utilise PyCharm qui a son propre intercepteur de raccourcis clavier. En raison de cela, toutes les règles sont mises sur liste noire de PyCharm à l'étape de composition/décomposition.

compose.py :

import json
from pathlib import Path

p_decomposed = Path('decomposed/')

# Load scaffold
p_scaffold = p_decomposed / 'scaffold.json'
with p_scaffold.open() as f:
    scaffold = json.load(f)

# Load rules
p_rules = p_decomposed / 'rules'
for p_rule in sorted(p_rules.iterdir()):
    if p_rule.stem.startswith('.'):
        continue
    print(p_rule)

    p_rule_json = p_rule / 'rule.json'
    with p_rule_json.open() as f:
        rule = json.load(f)

    p_manipulators = p_rule / 'manipulators'
    for p_manipulator in sorted(p_manipulators.iterdir()):
        with p_manipulator.open() as f:
            j = json.load(f)

        rule['manipulators'].append(j)

    profiles = scaffold['profiles']
    first_prof = profiles[0]
    complex_mods = first_prof['complex_modifications']
    rules = complex_mods['rules']
    rules.append(rule)

p_composed = Path('karabiner.json')
with p_composed.open('w') as f:
json.dump(scaffold, f, indent=4)

decompose.py :

import json
from pathlib import Path

with open('karabiner.json') as f:
    j = json.load(f)

profiles = j['profiles']
first_prof = profiles[0]
complex_mods = first_prof['complex_modifications']
rules = complex_mods['rules']

# Dump everything except the rules into a "scaffold file"
complex_mods['rules'] = []
with open('decomposed/scaffold.json', 'w') as f:
    json.dump(j, f, indent=4)

def normalize_rule_name(raw_name):
    """
    Normalize rule name by removing special characters, to make it suitable
    for use as a file name.
    """
    lowered = raw_name.lower()

    filtered = ''
    for c in lowered:
        if c.isalnum():
            filtered += c
        else:
            filtered += '-'

    while '--' in filtered:
        filtered = filtered.replace('--', '-')

    if filtered.endswith('-'):
        filtered = filtered[:-1]

    return filtered

def blacklist_pycharm(manipulator):
    pattern = "^com\\.jetbrains\\."

    if 'conditions' not in manipulator:
        return

    for c in manipulator['conditions']:
        if c.get('type', '') != 'frontmost_application_unless':
            continue

        if pattern not in c['bundle_identifiers']:
            c['bundle_identifiers'].append(pattern)

def process_manipulator(manipulator):
    """
    Gets applied to every manipulator before dumping it to a file.
    """
    result = dict(manipulator)

    blacklist_pycharm(result)

    return result

# Dump each rule to a separate file
for n, rule in enumerate(rules):
    # Normalize name
    desc = rule['description']
    desc_norm = normalize_rule_name(desc)

    # Pull out manipulators and save the rest
    manipulators = rule['manipulators']
    rule['manipulators'] = []

    p_rule = Path('decomposed/rules') / f'{n:03d}_{desc_norm}' / 'rule.json'
    p_rule.parent.mkdir(exist_ok=True)

    with p_rule.open('w') as f:
        json.dump(rule, f, indent=4)

    # Dump each manipulator
    p_manipulators = p_rule.parent / 'manipulators'
    p_manipulators.mkdir(exist_ok=True)
    for i, manipulator in enumerate(manipulators):
        p_m = p_manipulators / f'{i+1}.json'
        with p_m.open('w') as f:
            json.dump(process_manipulator(manipulator), f, indent=4)

4voto

furins Points 146

Non pas un éditeur, mais une alternative, une syntaxe plus concise et conviviale pour Karabiner est fournie par Goku.

Goku est un outil qui vous permet de gérer votre configuration Karabiner facilement, en s'appuyant sur le format de fichier EDN.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X