BetterCmdTab

Plik konfiguracyjny

Jak działa config.json — lokalizacja, włączanie, dwukierunkowa synchronizacja na żywo, schemat i obsługa błędów.

BetterCmdTab może przechowywać każde ustawienie w zwykłym pliku JSON, który synchronizuje się w obie strony z oknem ustawień. Zmień plik, a zmiana zostanie zastosowana na żywo; zmień coś w aplikacji, a plik zostanie zaktualizowany. Plik zaprojektowano tak, aby nadawał się do repozytorium z plikami konfiguracyjnymi.

Lokalizacja

~/.config/bettercmdtab/config.json

$XDG_CONFIG_HOME jest uwzględniany, gdy wskazuje ścieżkę bezwzględną. W takim przypadku plik znajduje się w $XDG_CONFIG_HOME/bettercmdtab/config.json.

Ścieżka może być dowiązaniem symbolicznym — przed zapisem jest rozwiązywana, dzięki czemu zastępowany jest cel dowiązania, a nie samo dowiązanie.

Włączanie

Samo istnienie pliku włącza funkcję. BetterCmdTab nigdy nie tworzy go samodzielnie.

  • Brak pliku — cała funkcja pozostaje nieaktywna. Nic nie jest zapisywane ani obserwowane.
  • Plik istnieje — zmiany są stosowane na żywo, a ustawienia zmienione w aplikacji zapisywane z powrotem.
  • Usunięcie pliku — synchronizacja zostaje zatrzymana.

Aby go utworzyć, użyj Ustawienia → Ogólne → Kopia zapasowa → Plik konfiguracyjny → Utwórz…. Spowoduje to zapisanie bieżących ustawień i uruchomienie synchronizacji. Możesz też utworzyć plik ręcznie, o ile katalog istniał już w chwili uruchomienia aplikacji:

mkdir -p ~/.config/bettercmdtab
echo '{}' > ~/.config/bettercmdtab/config.json

Jeśli podczas uruchamiania nie istniał ani ~/.config, ani ~/.config/bettercmdtab, aplikacja nie ma czego obserwować i plik utworzony później zostanie wykryty dopiero po ponownym uruchomieniu aplikacji (lub naciśnięciu Utwórz…). To celowe — obserwowanie $HOME w oczekiwaniu na pojawienie się .config budziłoby aplikację przy każdym zapisie pliku konfiguracyjnego.

Format

Płaski obiekt JSON z parami klucz: wartość. Klucze to nazwy preferencji Switcher.* bez prefiksu, dlatego Switcher.layoutMode jest zapisywany jako layoutMode.

~/.config/bettercmdtab/config.json
{
  "$schema": "schema.json",
  "layoutMode": "windowPreview",
  "sortOrder": "mruWindows",
  "spaceScope": "visibleSpaces",
  "panelScalePercent": 110,
  "stayOpenOnRelease": true,
  "pinnedBundleIDs": ["com.apple.Safari", "com.figma.Desktop"]
}

W pełni kwalifikowane klucze ("Switcher.layoutMode") również są akceptowane podczas odczytu, dzięki czemu stary plik napisany ręcznie nadal działa. Nigdy nie są zapisywane.

Format celowo nie ma wersji. Nieznane klucze są ignorowane, a brakujące zachowują bieżące wartości, dlatego plik można współdzielić między wersjami aplikacji w obu kierunkach.

Obsługa w edytorze

Obok config.json aplikacja zapisuje schema.json i wskazuje go w kluczu $schema pliku konfiguracyjnego. Jest to JSON Schema (draft 2020-12) generowany przez uruchomioną wersję aplikacji, więc nigdy nie pozostaje za nią w tyle: opisuje każdy klucz, każda wartość wyliczeniowa ma listę dozwolonych wartości z takimi samymi etykietami jak w oknie ustawień, a każdy klucz liczbowy zawiera akceptowany zakres.

Dzięki temu VS Code, środowiska JetBrains, Zed i każdy edytor z serwerem języka JSON oferują uzupełnianie, dokumentację po wskazaniu kursorem oraz sprawdzanie poprawności w tekście.

$schema jest wskaźnikiem, a nie ustawieniem — jest ignorowany podczas importu i nigdy nie jest przechowywany.

Działanie synchronizacji

Plik → aplikacja. Zapisy są scalane przez 200 ms i odczytywane poza głównym wątkiem, a następnie stosowane na głównym wątku. Obsługiwane są edytory zapisujące atomowo (zapis do pliku tymczasowego, a następnie zmiana nazwy na docelową) — obserwator ponownie dołącza się do nowego pliku.

Aplikacja → plik. Zmiany w oknie ustawień są zapisywane atomowo z opóźnieniem 500 ms. Oczekująca zmiana jest synchronicznie zapisywana podczas zamykania aplikacji, więc ostatnie zmienione ustawienie nie zostanie utracone.

Plik jest normalizowany przy każdym zapisie

Każda zastosowana zmiana zapisuje plik ponownie jako pełną kanoniczną migawkę — wszystkie aktualnie przechowywane ustawienia, czytelne formatowanie i klucze posortowane alfabetycznie. Częściowy plik napisany ręcznie zostanie rozszerzony przy pierwszej zmianie, a własne formatowanie nie zostanie zachowane.

To koszt dwukierunkowej synchronizacji — plik i okno ustawień nigdy nie mogą być sprzeczne. Jeśli chcesz przechowywać minimalny plik w systemie kontroli wersji, zachowaj własną kopię, a synchronizowany plik traktuj jako generowany. (JSON nie obsługuje komentarzy, więc nic innego nie zostanie utracone.)

Dlaczego plik ma mniej kluczy niż dokumentacja

Plik zawiera ustawienia, które zostały faktycznie zapisane, a nie wszystkie 85 udokumentowanych kluczy. Preferencja jest przechowywana po pierwszej zmianie (albo gdy zapisze ją migracja), dlatego nowa instalacja tworzy niemal pusty plik, który rośnie wraz z dostosowywaniem ustawień.

Nie stanowi to problemu: brak klucza oznacza „nadal ma wartość domyślną”, dokładnie tak jak traktuje go import. Dodaj ręcznie dowolny udokumentowany klucz, a zostanie natychmiast zastosowany.

Częściowe zmiany i obsługa błędów

Import jest zawsze częściowy i nigdy nie niszczy danych:

  • Pominięte klucze zachowują bieżącą wartość. Zapisanie {"layoutMode": "list"} zmienia układ i nic więcej.
  • Nierozpoznane klucze są ignorowane, dzięki czemu konfiguracja z nowszej wersji nadal zostanie zastosowana.
  • Nieprawidłowy JSON jest odrzucany w całości. Bieżące ustawienia zostają zachowane, a przyczyna trafia do dziennika; te same błędne bajty nie są ponownie analizowane przy każdym zapisie, a naprawienie pliku powoduje jego zastosowanie.
  • Wartości o nieprawidłowej strukturze — na przykład JSON null — są pomijane osobno dla każdego klucza. Ten klucz zachowuje wartość, a reszta pliku nadal jest stosowana.
  • Liczby spoza zakresu są ograniczane do akceptowanego zakresu widocznego w dokumentacji, a nie odrzucane.
  • Nierozpoznane wartości wyliczeniowe wracają do wartości domyślnej danego klucza.

Czego nie ma w pliku

Niektóre dane są celowo wykluczone i nie są ani eksportowane, ani importowane:

Wykluczone danePowód
Skróty wyzwalające ⌘Tab / ⌘`Rejestrator skrótów przechowuje je pod własnymi kluczami poza przestrzenią nazw Switcher.*
disabledSymbolicHotKeysRejestr natywnych skrótów wyłączonych na tym Macu — import kopii z innego Maca mógłby trwale wyłączyć natywny ⌘Tab
recentlyClosedHistoria sesji, a nie konfiguracja
customCommitSoundFilenamePlik dźwiękowy znajduje się w katalogu Application Support tego Maca
accentChoice, customAccentHexWycofane w 26.7 — przełącznik zawsze używa koloru akcentu macOS

Skróty o ograniczonym zakresie są przypadkiem pośrednim: scopedShortcutList zapisuje identyfikator, zakres i nazwę każdej pozycji, ale sam skrót jest rejestrowany poza tym plikiem. Synchronizacja pliku z nowym Makiem przenosi skróty; ich kombinacje klawiszy trzeba tam zarejestrować ponownie.

Alternatywa: eksport i import

Jeśli nie chcesz pliku synchronizowanego na żywo, w sekcji Ustawienia → Ogólne → Kopia zapasowa znajdziesz też jednorazowe przyciski Eksportuj ustawienia i Importuj ustawienia. Eksport zapisuje dokładnie ten sam płaski format JSON w wybranym pliku .json. Import akceptuje ten format, a także starszą otoczkę .cmdtab tworzoną przez wcześniejsze wersje.

Dokumentacja

Na tej stronie