Własna paczka

Paczka to jeden plik tekstowy. Wystarczy położyć go w folderze, a paleta pokaże jego wartości obok wbudowanych. Ta strona prowadzi od pustego folderu do pierwszej własnej wartości wpisanej w pole.

Czym jest paczka?

Paczka to jeden plik tekstowy w formacie TOML, nazwany tak jak paczka, z wartościami testowymi w kolejności, w jakiej tester je wpisuje. Każda wartość mówi, czym jest, co zwykle psuje w aplikacji i co poprawna aplikacja z nią robi. Tak wygląda cała paczka z jedną wartością:

format = 1

[pack]
id          = "first-pack"
name        = "First pack"
description = "Three values for a name field, to show how a pack is written."
version     = "1.0"
updated     = 2026-11-10
license     = "CC-BY-4.0"
authors     = ["Naughty Keyboard"]
language    = "en"
tags        = ["example", "names"]
fields      = ["name", "text"]
risk        = "normal"

[[values]]
id     = "trailing-space"
name   = "Name with a space at the end"
value  = "Kowalski\u0020"
breaks = "The sign-up form keeps the space and the login form trims it, or the other way round, so the account is created and then cannot be found."
expect = "Trimmed everywhere or kept everywhere, so the same name always finds the same account."
since  = "1.0"

Wiersze do pierwszego [[values]] opisują paczkę, a każdy blok [[values]] to jedna wartość. Tekst po znaku # to komentarz, który program pomija. Tekst stoi w cudzysłowach prostych, liczba i data bez nich, a lista w nawiasach kwadratowych.

Jak zrobić pierwszą paczkę?

  1. Otwórz własny folder. W palecie naciśnij AltShiftSpace , żeby otworzyć okno wartości, kliknij u góry Pack folders, a potem Create and open przy własnym folderze. Folder otworzy się w menedżerze plików.
  2. Połóż w nim szablon. Pobierz do tego folderu first-pack.toml albo inny z szablonów paczek.
  3. Otwórz plik w edytorze tekstu, na przykład w Notatniku, TextEdit albo edytorze kodu. Edytor dokumentów zapisuje formatowanie, którego program nie przeczyta.
  4. Zrób z niej swoją. Nadaj paczce własne id i zmień nazwę pliku tak samo, więc checkout.toml ma w środku id = "checkout". Potem zastąp przykładowe wartości swoimi.
  5. Użyj jej. Naciśnij znów AltShiftSpace : paczka jest na liście z dopiskiem own folder. Wybierz ją, kliknij w testowane pole i naciśnij AltShiftN .

Okno wartości czyta folder przy każdym otwarciu, więc zmianę w pliku widać bez restartu palety. Paczka z błędem jest na liście jako niewczytana, z liczbą problemów, a sprawdzanie paczki pokazuje, gdzie one są.

Kto używa wiersza poleceń, może zacząć od nkb new-pack checkout: zapisuje nowy plik paczki z jedną przykładową wartością, gotowy do edycji, a reszta tej strony dotyczy go tak samo.

Gdzie położyć plik?

We własnym folderze albo w folderze zespołu. Własny folder to packs obok pliku ustawień:

  • Windows: %APPDATA%\Naughty Keyboard\packs
  • macOS: ~/Library/Application Support/Naughty Keyboard/packs
  • Linux: ~/.config/naughty-keyboard/packs

Folder zespołu to dowolny folder, w którym zespół trzyma pliki paczek, opisany niżej. W obu plik paczki leży bezpośrednio w folderze, nie w folderze w środku, a jego nazwa to id paczki z końcówką .toml. Folder może mieć do 256 plików paczek, a jeden plik do 4 MiB.

Paczka o tym samym id co wbudowana jest używana zamiast niej, a paczka z własnego folderu zamiast tej z folderu zespołu. Paleta, okno wartości i blok do zgłoszenia mówią, skąd paczka pochodzi, więc nikt nie wpisuje wartości z jednej paczki, myśląc o innej.

Co jest na początku paczki?

Pierwszy wiersz, format = 1, a potem tabela [pack], która opisuje całą paczkę:

PoleWymaganeCo wpisać
idtakNazwa paczki dla programu: małe litery, cyfry i łączniki, na początku litera. Plik nazywa się tak samo, z końcówką .toml.
nametakKrótka nazwa, którą ludzie czytają w palecie, do 120 znaków.
descriptiontakJedno albo dwa zdania o tym, do czego jest paczka, do 300 znaków.
versiontakWersja wartości paczki, na przykład "1.0". Podnieś ją, gdy wartości się zmieniają.
updatedtakDzień ostatniej zmiany, jako 2026-11-10, bez cudzysłowów.
licensetakLicencja wartości, na przykład "CC-BY-4.0". Dla paczki, która zostaje w zespole, wpisz to, czego używa zespół, na przykład "proprietary".
authorstakLista nazwisk, na przykład ["Jan Kowalski"].
languagetakJęzyk, w którym są napisane zdania, na przykład "pl" albo "en".
tagszalecaneSłowa, po których wyszukiwarka okna wartości znajduje paczkę. Bez nich nkb lint ostrzega: paczkę znajdzie tylko ktoś, kto zna jej nazwę.
fieldsnieRodzaje pól, do których pasują wartości: any, text, multiline, name, username, password, email, url, search, number, integer, money, date, time, datetime, phone, postal-code, country-code, address, filename, path, id-number.
risknienormal, offensive. Wartość oznaczona offensive jest oznaczona w palecie, zanim zostanie wpisana.
sourcenieSkąd pochodzą wartości, gdy są czyjąś pracą.

Co jest w wartości?

Jeden blok [[values]] na każdą wartość:

PoleWymaganeCo wpisać
idtakWłasna nazwa wartości: małe litery, cyfry i łączniki, inna niż każde inne id w paczce. Blok do zgłoszenia cytuje wartość jako paczka/id, więc nie zmieniaj go, gdy inni już używają paczki.
nametakKrótka etykieta, którą pokazuje paleta.
valuetak, dla wartości zapisanej wprostTekst do wpisania, w cudzysłowach prostych.
breakstakCo ta wartość zwykle psuje i dlaczego, w co najmniej 40 znakach.
expectzalecaneCo robi z nią poprawna aplikacja. Bez tego nkb lint ostrzega.
sincetakversion paczki, w której wartość pojawiła się pierwszy raz.
fields, tags, risknieTo samo co na początku paczki, dla tej jednej wartości.
typenieWartość, którą wylicza program: "repeat" dla bardzo długiej wartości, "next-date" dla daty, która zawsze jest przed nami.

Paleta wpisuje wartości w kolejności, w jakiej stoją w pliku, więc wartość, która najpewniej znajdzie błąd, idzie pierwsza. Tester, który naciśnie AltShiftN pięć razy i pójdzie dalej, dostanie pięć najlepszych wartości. Paczka z więcej niż 60 wartościami działa, a nkb lint radzi ją podzielić.

Jak napisać dobre zdanie breaks?

Powiedz, co się psuje i dlaczego, żeby osoba, która wpisuje wartość, wiedziała, gdzie patrzeć. breaks to powód, dla którego paczka jest warta więcej niż lista napisów, i jedyna część, której nikt nie napisze za Ciebie. Zdanie jest po angielsku albo w języku z pola language.

  • Za krótkie, nkb lint je odrzuci: Breaks the login.
  • Mówi co, ale nie dlaczego: Login fails with a trailing space.
  • Mówi co i dlaczego: The sign-up form keeps the space and the login form trims it, or the other way round, so the account is created and then cannot be found.

expect to druga połowa: co robi poprawna aplikacja, żeby tester odróżnił błąd od właściwej odpowiedzi. Dla wartości wyżej: Trimmed everywhere or kept everywhere, so the same name always finds the same account.

Jak zapisać znak, którego nie widać?

Jako sekwencję ucieczki w cudzysłowach prostych, na przykład \u0020 dla spacji na końcu. Znak, którego nie widać, przetrwa jeden edytor i zniknie w następnym, a recenzent nie ma jak zobaczyć, że w ogóle tam jest. Wszystko, co widać, zostaje jak jest: litery z ogonkami i akcentami, inne pisma i emoji zapisuje się wprost.

ZapisZnak
\u0020spacja na początku albo na końcu wartości
\u00A0twarda spacja
\ttabulator, który paleta wpisuje klawiszem Tab
\nnowy wiersz, który paleta wpisuje klawiszem Enter
\u200Bspacja o zerowej szerokości
\u202Eznak odwracający kierunek tekstu
\uFEFFznacznik kolejności bajtów
\\ukośnik wsteczny
\"cudzysłów prosty
\U0001F600dowolny znak po numerze, z ośmioma cyframi dla znaku powyżej \uFFFF

Litera, która wygląda jak inna, na przykład cyrylickie o wśród liter łacińskich, też lepiej wygląda jako \u043E, bo recenzent widzi wtedy, że to nie jest o.

Nie wiadomo, które znaki tego wymagają? Wpisz wartość tak, jak jest, i uruchom nkb lint: nazwie każdy znak, który trzeba zapisać inaczej, i poda zapis.

W apostrofach nic nie jest sekwencją ucieczki. Dlatego 'C:\temp' to ścieżka dokładnie tak, jak jest zapisana, a 'Kowalski\u0020' to znaki \u0020, a nie spacja. Wartość z sekwencją ucieczki zapisuj w cudzysłowach prostych.

Jak zapisać bardzo długą wartość?

Jako krótki kawałek i liczbę powtórzeń, z type = "repeat", zamiast całej wartości:

[[values]]
id     = "len-51"
name   = "51 characters, one over the limit"
type   = "repeat"
unit   = "a"
count  = 51
breaks = "A limit checked only in the browser lets it through when the request is sent another way, and a database column of 50 cuts the last letter or refuses the row with a raw error."
expect = "Refused with a message that names the limit, and never saved cut short."
since  = "1.0"

unit to kawałek, który może mieć sekwencje ucieczki, a count to liczba powtórzeń, od 1 do 1 000 000. Cała wartość może mieć do 1 000 000 punktów kodowych. Paleta wpisuje ją w całości, w tempie, w jakim aplikacja przyjmuje znaki, a Escape ją zatrzymuje. Wartość zapisana wprost, dłuższa niż 2 000 znaków i złożona z jednego powtórzonego kawałka, dostaje od nkb lint ostrzeżenie z radą, żeby użyć repeat.

Jak zapisać datę, która zawsze jest w przyszłości?

Jako regułę dnia, z type = "next-date", zamiast samej daty:

[[values]]
id      = "spring-forward"
name    = "Check-in at an hour the clocks skip"
type    = "next-date"
month   = 3
week    = "last"
weekday = "sunday"
time    = "02:30"
breaks  = "On the night clocks go forward in the European Union this hour does not exist, so a form moves it to 03:30 without saying so, or fails with a raw error."
expect  = "Refused with an explanation, or moved with the new time shown."
since   = "1.0"

W chwili wpisania program wylicza pierwszy dzień, który pasuje do reguły i jest co najmniej dwa dni po dzisiejszym w UTC, więc jest przyszłością w każdej strefie czasowej. Wpisuje go jako YYYY-MM-DD, a z polem time jako YYYY-MM-DD HH:MM. Data zapisana wprost któregoś dnia przechodzi w przeszłość i po cichu przestaje testować to, co obiecuje.

  • month to od 1 do 12.
  • week to tydzień miesiąca: first, second, third, fourth, last.
  • weekday to monday, tuesday, wednesday, thursday, friday, saturday, sunday.
  • time jest opcjonalne, jako HH:MM w zapisie 24-godzinnym.

Blok do zgłoszenia podaje dzień, który został wpisany, więc znalezisko da się wpisać ponownie dokładnie tak samo.

Jak zrobić parę?

Zapisz dwie wartości jedna po drugiej, a potem blok [[pairs]], który je łączy. Para to dwie wartości wpisywane w dwa pola, na przykład adres e-mail i pole, które go powtarza:

[[values]]
id     = "email"
name   = "E-mail address"
value  = "jan.kowalski@example.com"
breaks = "The first half of a pair, and on its own a plain address every form takes. Type it into the e-mail field, then the next value into the field that repeats it."
expect = "Accepted."
since  = "1.0"

[[values]]
id     = "email-trailing-space"
name   = "The same address with a space at the end"
value  = "jan.kowalski@example.com\u0020"
breaks = "The second half of the pair. A form that trims one field and not the other says the two addresses differ, or saves the address with the space and no mail arrives."
expect = "Trimmed in both fields, and accepted as the same address."
since  = "1.0"

[[pairs]]
id       = "repeat-email"
name     = "E-mail and the field that repeats it"
relation = "identity"
a        = "email"
b        = "email-trailing-space"
breaks   = "The two fields are compared before they are trimmed, so a person who typed the same address twice is told the addresses differ."
expect   = "Both fields trimmed the same way, and the two accepted as one address."
since    = "1.0"

a i b to id obu wartości, a b stoi w pliku zaraz po a, bo drugie naciśnięcie wpisuje to, co jest następne. Paleta pokazuje pair 1 of 2 i pair 2 of 2 przy nazwie każdej połowy. relation to jedno z: look-alike, range, identity:

  • look-alike: dwie wartości, które wyglądają tak samo, a różnią się bajtami, na przykład dwa loginy w dwóch alfabetach.
  • range: początek i koniec, na przykład start wieczorem i koniec rano.
  • identity: dwie wartości, które aplikacja powinna uznać za te same albo za różne, na przykład hasło i jego powtórzenie.

Jak sprawdzić paczkę?

Uruchom nkb lint checkout.toml, z nazwą swojego pliku. Sprawdza plik wobec każdej reguły formatu i wypisuje od razu wszystkie problemy, każdy w osobnym wierszu, a na końcu podaje, ile błędów i ostrzeżeń znalazł. Przykłady niżej pokazują, co wypisuje.

Wiersz podaje plik, wiersz z problemem, kod i zdanie, które mówi, co zrobić. Kod zaczynający się od E to błąd: paczka nie wczyta się, dopóki go nie poprawisz. Kod zaczynający się od W to ostrzeżenie: paczka się wczyta, a zdanie mówi, co by zyskała. Potem nkb fmt checkout.toml wyrównuje plik tak, jak oczekuje nkb lint, i nigdy nie zmienia wartości. nkb lint i nkb fmt opisują każdą opcję.

nkb to wiersz poleceń, drugi program każdego wydania. Instalator na Windows dodaje go do PATH razem z paletą, a Pobieranie ma jego archiwum dla każdego systemu.

Co znaczą najczęstsze błędy?

Każdy przykład niżej to plik z jednym błędem i to, co nkb lint o nim mówi, słowo w słowo. Program mówi po angielsku.

Nazwa pliku i id się różnią

W pliku file-name.toml:

3[pack]
4id          = "my-shop"
5name        = "My shop"
6description = "Values for the checkout of my shop."
7version     = "1.0"
8updated     = 2026-11-10
9license     = "CC-BY-4.0"
10authors     = ["Me"]
11language    = "en"
12tags        = ["checkout"]

Co mówi nkb lint:

$ nkb lint file-name.toml
file-name.toml:4  E010  the pack declares id `my-shop`, which is not this file's name. A pack is addressed by its file name, so rename one of the two to match the other.
1 error, 0 warnings.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Zmień nazwę pliku albo id, żeby były takie same. Paleta znajduje paczkę po nazwie pliku.

Wartość nie ma breaks

W pliku no-breaks.toml:

14[[values]]
15id     = "trailing-space"
16name   = "Name with a space at the end"
17value  = "Kowalski\u0020"
18expect = "Trimmed everywhere or kept everywhere."
19since  = "1.0"

Co mówi nkb lint:

$ nkb lint no-breaks.toml
no-breaks.toml:14  E030  value `trailing-space` declares no `breaks`. It is the field this catalogue exists for: say what this value usually breaks and why, or the value is a curiosity rather than a test case.
1 error, 0 warnings.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Dopisz do wartości breaks, zdanie o tym, co psuje.

Zdanie breaks jest za krótkie

W pliku short-breaks.toml:

14[[values]]
15id     = "trailing-space"
16name   = "Name with a space at the end"
17value  = "Kowalski\u0020"
18breaks = "Breaks the login."
19expect = "Trimmed everywhere or kept everywhere."
20since  = "1.0"

Co mówi nkb lint:

$ nkb lint short-breaks.toml
short-breaks.toml:18  E031  value `trailing-space` has a `breaks` of 17 characters, where the format asks for 40. Say what this value usually breaks and why - the sentence is the work this catalogue is made of.
1 error, 0 warnings.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Powiedz, co się psuje i dlaczego, w co najmniej 40 znakach.

Spacja jest zapisana wprost

W pliku space-written-out.toml:

14[[values]]
15id     = "trailing-space"
16name   = "Name with a space at the end"
17value  = "Kowalski "
18breaks = "The sign-up form keeps the space and the login form trims it, so the account is created and then cannot be found."
19expect = "Trimmed everywhere or kept everywhere."
20since  = "1.0"

Co mówi nkb lint:

$ nkb lint space-written-out.toml
space-written-out.toml:17  E020  value `trailing-space` writes \u0020 out instead of escaping it. A reviewer cannot see it and an editor can drop it - write it as \u0020.
1 error, 0 warnings.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Wartość kończy się spacją, której nikt nie widzi. Zapisz ją jako \u0020, tak jak mówi zdanie.

Wartość w apostrofach potrzebuje sekwencji ucieczki

W pliku single-quotes.toml:

14[[values]]
15id     = "trailing-space"
16name   = "Name with a space at the end"
17value  = 'Kowalski '
18breaks = "The sign-up form keeps the space and the login form trims it, so the account is created and then cannot be found."
19expect = "Trimmed everywhere or kept everywhere."
20since  = "1.0"

Co mówi nkb lint:

$ nkb lint single-quotes.toml
single-quotes.toml:17  E022  value `trailing-space` needs \u0020 escaped, but is written in single quotes where nothing is an escape. Use double quotes and write \u0020.
1 error, 0 warnings.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Ujmij wartość w cudzysłowy proste i zapisz spację jako \u0020.

Plik nie jest poprawnym TOML

W pliku curly-quotes.toml:

14[[values]]
15id     = "trailing-space"
16name   = “Name with a space at the end”
17value  = "Kowalski\u0020"
18breaks = "The sign-up form keeps the space and the login form trims it, so the account is created and then cannot be found."
19expect = "Trimmed everywhere or kept everywhere."
20since  = "1.0"

Co mówi nkb lint:

$ nkb lint curly-quotes.toml
curly-quotes.toml:16  E004  not valid TOML: string values must be quoted, expected literal string. Nothing else in this file could be checked.
1 error, 0 warnings.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Nazwa stoi w cudzysłowach drukarskich, które niektóre edytory wstawiają zamiast prostych. TOML przyjmuje tylko proste. Wpisz je jeszcze raz albo użyj edytora, który ich nie zamienia. Ten sam błąd daje niezamknięty cudzysłów albo brakujący nawias.

Rodzaju pola nie ma na liście

W pliku wrong-field-kind.toml:

14[[values]]
15id     = "trailing-space"
16name   = "Name with a space at the end"
17value  = "Kowalski\u0020"
18breaks = "The sign-up form keeps the space and the login form trims it, so the account is created and then cannot be found."
19expect = "Trimmed everywhere or kept everywhere."
20fields = ["e-mail"]
21since  = "1.0"

Co mówi nkb lint:

$ nkb lint wrong-field-kind.toml
wrong-field-kind.toml:20  E028  value `trailing-space` names field kind `e-mail`, which is not in the format's closed list: any, text, multiline, name, username, password, email, url, search, number, integer, money, date, time, datetime, phone, postal-code, country-code, address, filename, path and id-number. Pick the nearest one rather than coining one.
1 error, 0 warnings.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Wybierz najbliższe słowo z listy w zdaniu, tutaj email.

Literówka w nazwie pola

W pliku typo-in-a-key.toml:

14[[values]]
15id       = "trailing-space"
16name     = "Name with a space at the end"
17value    = "Kowalski\u0020"
18breaks   = "The sign-up form keeps the space and the login form trims it, so the account is created and then cannot be found."
19since    = "1.0"
20expected = "Trimmed everywhere or kept everywhere."

Co mówi nkb lint:

$ nkb lint typo-in-a-key.toml
typo-in-a-key.toml:14  W032  value `trailing-space` declares no `expect`. Without it a tester sees what happened and has nothing to compare it against, so a bug and correct behaviour look the same.
typo-in-a-key.toml:20  E002  `trailing-space` declares `expected`, which the format does not define. A key nobody reads is a setting nobody applied - check for a typo.
1 error, 1 warning.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Format nie ma pola expected, więc wartość liczy się tak, jakby nie miała expect wcale. Popraw nazwę, a znikną oba wiersze.

Plik nie jest wyrównany

W pliku untidy.toml:

14[[values]]
15id = "trailing-space"
16name   = "Name with a space at the end"
17value  = "Kowalski\u0020"
18breaks = "The sign-up form keeps the space and the login form trims it, so the account is created and then cannot be found."
19expect = "Trimmed everywhere or kept everywhere."
20since  = "1.0"

Co mówi nkb lint:

$ nkb lint untidy.toml
untidy.toml:15  W064  this file is not in the shape `nkb fmt` writes. Run `nkb fmt` on it, and a difference in a pull request stays a difference of content rather than of style.
0 errors, 1 warning.
Checked 43 of 49 rules, 1 of them only in part. 5 not checked - run `nkb lint --explain` to see which and why.
The pack format is not frozen yet: a later release may still change it.

Uruchom nkb fmt untidy.toml. Wyrównuje znaki równości i ustawia pola w kolejności, a wartości nigdy nie zmienia.

Czy zespół może mieć wspólne paczki?

Tak. Trzymajcie pliki paczek we wspólnym folderze, na przykład w folderze qa-packs w repozytorium testowanej aplikacji. Każdy tester raz wskazuje go palecie: Pack folders w oknie wartości, potem Choose folder, albo upuszcza folder na to okno. Paleta mówi o tym oknie więcej.

Folder zespołu na udziale sieciowym, który nie odpowie w 2 sekundy, jest pomijany ze zdaniem, które to mówi, a pozostałe paczki działają dalej. W potoku CI --team-folder wskazuje folder na jedno uruchomienie, więc build może sprawdzić paczki i ich użyć:

$ for f in qa-packs/*.toml; do nkb lint "$f" || exit 1; done
$ nkb emit checkout --team-folder qa-packs --format json > checkout.json

Czy mogę napisać paczkę po polsku?

Tak. Ustaw language na swój język, na przykład "pl", i pisz w nim name, description, breaks i expect. Nazwy pól i słowa z zamkniętych list, takie jak email czy look-alike, zostają bez zmian, bo czyta je program.

Czy mogę zmienić wbudowaną paczkę?

Tak, kładąc we własnym folderze paczkę o tym samym id: jest używana zamiast wbudowanej, a paleta to mówi. Pliki wbudowanych paczek są w folderze packs w repozytorium, do skopiowania i zmiany. Wartość, która przyda się wszystkim, lepiej zaproponować, z tym, co psuje i gdzie się trafiła.

Czy format jest ostateczny?

Jeszcze nie. Kolejne wydanie może go zmienić, a jego notatki powiedzą jak. nkb lint mówi to przy każdym uruchomieniu, żeby plik, który przechodzi dziś, nie był czytany jako obietnica na jutro.