12 votos

¿Existe un editor fácil de usar para las modificaciones complejas de Karabiner?

Tengo una gran lista de modificaciones complejas de Karabiner y es difícil hacer un seguimiento de todas ellas incluyendo conflictos, aplicaciones excluidas, etc. Por lo que veo, se espera que el usuario edite ~/.config/karabiner/karabiner.json a mano. Sin embargo, esto no es práctico en absoluto, ya que cada definición de modificación termina siendo bastante verbosa y sólo puedo ver 1-2 por pantalla. ¿Hay algún método más eficiente que me esté perdiendo? O debería escribir mi propio programa para generar el karabiner.json ¿archivo?

14voto

Jonne Haß Puntos 101

Hay un sencillo editor web estos días por cortesía de @genesy: https://genesy.github.io/karabiner-complex-rules-generator/

0 votos

¡Bienvenido a Ask Different! Estamos tratando de encontrar las mejores respuestas y esas respuestas proporcionarán información de apoyo de por qué son los mejores. Las respuestas deben ser autocontenidas, así que explica por qué crees que la respuesta que has proporcionado resolverá el problema o es mejor/más completa que las otras ya proporcionadas. Véase Cómo responder sobre cómo dar una respuesta de calidad. - De la revisión

6voto

Donentolon Puntos 9

Encontré Goku (ver respuesta de furins) y algunas otras herramientas pero ninguna parecía más fácil que editar el JSON. Al final escribí mis propios scripts que compartiré aquí.

Hay dos archivos de Python:

  • decompose.py toma un JSON de karabiner y lo divide en muchos archivos y directorios, para que puedas editar una regla a la vez.
  • compose.py toma estos directorios y los enrolla en un único JSON que karabiner aceptará.

Mantengo tanto el JSON único como los directorios descompuestos (así como el script) en mi repo de dotfiles. Cuando quiero alterar un keybind, creo un directorio para él (el método más fácil es copiar uno existente y modificarlo) y luego hago una codificación/decodificación de ida y vuelta. Por ejemplo..: python compose.py; python decompose.py; python compose.py .

Después de esto mi primer paso es comprobar git diff para ver si mi nueva regla tiene algún error que lo haya roto todo. Si es así, tengo muchas opciones para revertir los cambios a través de git y lo intento de nuevo. Una vez hecho esto, pruebo el keybind con Karabiner-EventViewer y su caso de uso previsto, y lo confirmo.

Los scripts son obviamente limitados y poco prácticos, porque son para uso personal (y creo que la solución "adecuada" para esto sería simplemente no usar un Mac, har har). Sugiero empezar con un JSON conocido que funcione como Atajos estilo PC para que puedas ver cómo funcionan las normas existentes. Funcionan razonablemente bien, pero algunas advertencias:

  • Cada regla va en un directorio. El nombre del directorio se construye a partir de un número (para evitar que las reglas cambien de orden y confundan a git) y el nombre de la regla. Obviamente, los nombres de las reglas pueden tener caracteres especiales, pero los directorios no, por lo que hay una extraña normalización que tuve que hacer con eso. Puede ser un poco frágil si haces cosas extravagantes con el nombre de la regla.
  • Uso PyCharm que tiene su propio interceptor de atajos de teclado. Debido a esto, todas las reglas están en la lista negra de PyCharm en la etapa de composición/descomposición.

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)

descomponer.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)

0 votos

Gracias por compartir su solución. Estoy de acuerdo en que Goku ayuda a reducir el tamaño del documento pero no su complejidad. Al dividir el archivo de configuración en partes más pequeñas tu solución ayuda mucho a mantener las cosas simples. Corrígeme si me equivoco pero parece que también puedes dejar, por ejemplo, un archivo txt en una carpeta descompuesta para almacenar algunas notas sobre la regla, eso puede ser extremadamente útil.

0 votos

@furins No hay problema - ojalá tuviera tiempo para limpiar y mantener esto.

0 votos

Tienes razón - sólo mirará rule.json en el directorio de reglas. Sin embargo, en el manipulators se cargará todo, así que si pones un archivo que no sea json ahí, se bloqueará por encima de rule['manipulators'].append(j) .

4voto

furins Puntos 126

No se trata de un editor, sino de una sintaxis alternativa, más concisa y amigable para Karabiner, proporcionada por Goku .

Goku es una herramienta que le permite gestionar la configuración de su Karabiner con facilidad, aprovechando Formato de archivo EDN .

0 votos

En realidad encontré a Goku pero era aún más confuso que el JSON, así que no me sirvió. Pero como esto responde técnicamente a mi pregunta, lo acepto por si ayuda a otros. Gracias.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X