Miniatura artykułu

Tworzenie własnych snippetów w Visual Studio Code

13 minut

Skopiuj link

Data publikacji: 6/9/2023, 7:15:45

Ostatnia aktualizacja: 4/1/2024

Snippety - czyli co?

Jeżeli miałeś okazję pisać w swoim życiu kod (w dowolnym języku programowania), to istnieje spora szansa, że korzystałeś już z tej funkcjonalności, nawet jeżeli nie jesteś tego świadomy.

Snippety (gdybym musiał to przetłumaczyć, to prawdopodobnie użyłbym słowa - skrawki lub strzępki, jednak będę się trzymać angielskiej wersji) to nic innego jak predefiniowane "strzępki" kodu, które tworzymy wcześniej, a następnie używamy za pomocą skrótów. W ten sposób możemy znacznie przyspieszyć wykonywanie powtarzalnych czynności (a tym samym zwiększyć efektywność), takich jak tworzenie różnego rodzaju boilerplate'ów, funkcji, klas, komponentów, itd.

W przypadku VSC nie potrzebujemy żadnych dodatkowych rozszerzeń żeby zacząć, a cała funkcjonalność jest wbudowana w IDE.

Podstawy

Zacznijmy od początku, czyli od przejścia do edytora snippetów. Screen poniżej ilustruje wersję dla Windowsa (File > Preferences > Configure User Snippets). Jeżeli pracujesz na macu, to ścieżka powinna wyglądać tak Code > Preferences.

Ścieżka do konfiguracji własnych snippetów

Ścieżka do konfiguracji własnych snippetów

Po wybraniu Configure User Snippets powinniśmy zobaczyć dropdown w którym mamy możliwość wyboru języka dla którego będziemy tworzyć skróty. Oczywiście wybór tej opcji zależy tylko od Ciebie, jednak w tym artykule skupimy się na JavaScript.

Wybór języka, dla którego tworzymy snippety

Wybór języka, dla którego tworzymy snippety

Od tego wyboru zależy w którym języku będą dostępne utworzone snippety, dlatego jeżeli planujesz stworzyć kawałki kodu, które wykorzystasz później w CSS, to właśnie ten język powinieneś wybrać.

Widok, który zobaczysz powinien przypominać ten:

Linie 1-5 opisują podstawową składnię stosowaną przy tworzeniu snippetów, a niżej widzimy prosty przykład z predefiniowanym kawałkiem kodu. Nie będziemy się skupiać co dokładnie się tam dzieje, zamiast tego stworzymy coś jeszcze bardziej trywialnego i poznamy wszystkie właściwości krok, po kroku.

Zanim przejdziemy dalej, krótkie wprowadzenie do formatu JSON (JavaScript Object Notation, który jest używany w VSC do konfiguracji (także snippetów). Jeżeli znasz podstawy, to możesz pominąć tą część i od razu przejść dalej.

Czym jest JSON?

W skrócie jest to tekstowy format danych bazujący na składni wykorzystywanej w obiektach JavaScript. Jest szeroko wykorzystywany w komunikacji klient - serwer oraz różnego rodzaju konfiguracjach. Oczywiście nie są to wszystkie zastosowania JSONa, a jedyne kilka wybranych.

Najważniejsze różnice pomiędzy składnią obiektu w JS a JSONem:

  • wszystkie klucze w JSON muszą być zapisane w podwójnym cudzysłowie

  • nie wszystkie wartości znane z JS są obsługiwane. JSON służy do zapisywania danych tekstowych, a więc nie obsługuje funkcji, metod, symboli, itp.

  • w JSON nie można użyć undefined, zamiast tego powinniśmy wykorzystać null

  • nie można również użyć NaN

  • string musi być w podwójnym cudzysłowie

  • po ostatniej wartości w obiekcie nie może występować , (przecinek)


Dokładny opis składni znajdziesz tutaj (trzeba poświęcić chwilę na zaznajomienie się z diagramami zastosowanym do opisania poszczególnych wartości).

Przykładowe dane zapisane w formacie JSON.

Pierwszy snippet

Niewątpliwie jedna z najczęściej używanych metod przez programistów front-end to console.log(), dlatego od niej zaczniemy naukę.
Tak jak wspomniałem wcześniej, całość powinna być zapisana w formacie JSON, dlatego zwróć uwagę, by kod pisać wewnątrz obiektu ({ ... }), który jest początkowo stworzony. Jeżeli plik jest pusty to koniecznie utwórz w nim obiekt, a dopiero wewnątrz pisz kod.

Przeanalizujmy co dokładnie dzieje się w powyższym przykładzie:

  1. Linie 1 oraz 6: to główny obiekt w pliku - w nim tworzymy snippety. W każdym kolejnym przykładzie również będę go stosować, ale dla oszczędności czasu pominę jego opis.

  2. Linia 2: to klucz, do którego przypiszemy snippet. Powinien być unikatowy (w teorii możemy dodać pod spodem kolejny takim sam klucz, jednak nadpisze on poprzedni).

  3. Linia 3: prefix, czyli skrót którego będziemy używać do wywołania tworzonego skrawka kodu. Powinien być możliwie prosty i intuicyjny. W tym przypadku stosujemy litery clg (jest to oczywiście mój osobisty wybór i dla Ciebie może nie być najlepszy) pochodzące od console.log.

  4. Linia 4: body to kod, który zostanie podstawiony w miejsce użytego skrótu (prefixu). To właśnie tutaj definiujemy jak dokładnie ma się zachowywać snippet.

Pamiętaj, że po jakichkolwiek zmianach należy zapisać plik konfiguracyjny.

W dalszej części artykułu poznasz więcej możliwości konfiguracji. Te, które wymieniłem wyżej są obowiązkowe - bez nich nie uzyskamy pożądanego efektu. Istnieje jednak kilka opcjonalnych właściwości, które mogą okazać się bardzo przydatne w przyszłości.

Body - ciało snippeta

To rozbudowany temat, dlatego będziemy poznawać kolejne możliwości na przykładach. Zacznijmy od czegoś prostego:

Jak widzisz body zawiera w tablicy kilka stringów, każdy z nich to kolejna linia kodu, zatem utworzony kawałek kodu posiada 3 linie kodu. W każdej chwili możemy go rozbudować o następne, wystarczy dodać kolejne wartości do tablicy.

  • $1, $2 - to specjalny zapis rozumiany przez VSC. W ten sposób oznaczamy miejsca do których będziemy "przeskakiwać" za pomocą klawisza tab po użyciu snippeta. Kolejność jest zależna od liczby podanej po znaku $. Nie ma ograniczeń co do liczby, dlatego możesz dodać tyle przeskoków, ile potrzebujesz.

  • ${1:\"placeholder\"} - rozbudowana wersja poprzedniego zapisu. Nadal oznacza, że w tym miejscu zatrzymamy się w przypadku użycia klawisza tab. Różnica polega na tym, że będzie tu już wpisana domyślna wartość "placeholder". Po przejściu do tego miejsca całość zostanie zaznaczona, dzięki czemu łatwo można ją podmienić na własną, dopasowaną do kontekstu.

  • $0 - chociaż zapis wygląda identycznie jak w pierwszym przypadku, to znaczenie jest inne. Użycie cyfry zero oznacza, że wskazujemy miejsce w którym ma się znaleźć kursor po przejściu przez wszystkie poprzednie kroki.

  • \ - został użyty jako escape character, czyli specjalny znak, który oznacza, że znak występujący bezpośrednio po nim powinien zostać potraktowany jako zwykły tekst (usuwa specjalne znaczenie niektórych znaków). Gdybym go nie użył, to " zostałby potraktowany jako zakończenie stringa, co spowodowałoby błąd.

Użycie

Przejdź do dowolnego pliku z rozszerzeniem odpowiadającym językowi, który wybrałeś w pierwszym kroku. Dla mnie będzie to po prostu dowolny plik *.js.

Jedyne co musisz zrobić, to wpisać skrót klawiszowy (prefix), który nadałeś wcześniej, zaczekać na podpowiedź edytora, a następnie nacisnąć enter.

Użycie snippeta w VSC

Użycie snippeta w VSC

Ponieważ w ciele snippeta zastosowaliśmy zmienną $1 to właśnie tutaj zostanie umieszczony kursor. Następnie użyciu tab, zostaniemy przeniesieni do linii 4, ponieważ została tu użyta zmienna $2. Kolejne naciśnięcie klawisz tab sprawi, że znajdziemy się w linii 3 - użycie $0 spowodowało, że jest to końcowa pozycja kursora.

Zaawansowana konfiguracja

Tak jak wspomniałem wcześniej opcji konfiguracji jest nieco więcej, nie jesteśmy ograniczeni jedynie do prefixu oraz body.

Omówmy właściwości, których do tej pory nie poznaliśmy, oraz te, które uległy zmianie:

  • prefix - występuje tutaj w postaci tablicy. Dzięki takiemu zapisowi mamy dostęp do utworzonego snippeta za pomocą kilku różnych skrótów

  • description - to po prostu opis. VSC będzie go wyświetlać podczas każdego użycia. W ten sposób znacznie łatwiej jest zapamiętać co robi dany kawałek kodu (szczególnie w bardziej rozbudowanych przypadkach)

  • scope - zakres, którego dotyczy dany snippet. W powyższym przykładzie zastosowałem zapis javascript, typescript - oznacza to, że VSC będzie podpowiadać możliwość użycia tylko podczas korzystania ze wskazanych języków. Możliwe jest również ograniczenie do danego projektu, jednak jest to na tyle rzadko używane, że nie będę tutaj opisywać takiego zastosowania.

  • isFileTemplate - ustawienie tego parametru na true daje możliwość podmiany zawartości całego pliku z wykorzystaniem snippeta. Jest to sporadycznie używana właściwość, jednak może się okazać przydatna podczas tworzenia np. klas, komponentów itp. Jeżeli zdecydujesz się ją wykorzystać, to utworzony kawałek kodu będzie widoczny po zastosowaniu komendy Snippets: Fill File With Snippet

    FileTemplate snippet - przykład

    FileTemplate snippet - przykład

Przyjrzyj się zdjęciu poniżej żeby jeszcze lepiej zrozumieć gdzie są używane poszczególne opcje konfiguracyjne.

Poszczególne właściwości snippeta w praktyce

Poszczególne właściwości snippeta w praktyce

Zmienne

Pozwalają dodać nieco dynamiki do statycznych kawałków kodu. Wszystkie zmienne zaczynają się od znaku $, a następnie wartość zmiennej np. $1, jeżeli ten zapis wygląda znajomo to bardzo dobrze. Do tej pory kilka razy wykorzystaliśmy już zmienne (chociaż nie użyliśmy tego nazewnictwa), teraz poznamy ich możliwości na jeszcze bardziej zaawansowanych przykładach.

Najczęściej używane zmienne

Pełną listę dostępnych wartości możesz znaleźć tutaj, ja opiszę te, które są najczęściej wykorzystywane:

  • TM_FILENAME - nazwa obecnie otwartego pliku

  • TM_FILENAME_BASE - nazwa obecnie otwartego pliku bez jego rozszerzenia

  • RELATIVE_FILEPATH - relatywna (w stosunku do obecnie otwartego folderu) ścieżka do obecnie otwartego pliku

  • RANDOM_HEX - losowa wartość w postaci Hexa

  • RANDOM - 6 losowych cyfr

  • BLOCK_COMMENT_START - początek komentarza blokowego. Automatycznie zostaje wybrany odpowiedni format w zależności od języka.

  • BLOCK_COMMENT_END - koniec komentarza blokowego. Automatycznie zostaje wybrany odpowiedni format w zależności od języka

  • LINE_COMMENT - komentarz liniowy. Automatycznie zostaje wybrany odpowiedni format w zależności od języka

Pamiętaj, że każda zmienna musi być poprzedzona znakiem $, inaczej zostanie potraktowana jako zwyczajny tekst. Alternatywnym zapisem jest użycie ${NAZWA_ZMIENNEJ}, zapis ten jest wymagany w przypadku używania transformatorów zmiennych (omówimy je na samym końcu), lub łączenia zmiennych z tekstem.

Uwaga! ten przykład nie działa poprawnie. Zamiast nazwy pliku zobaczymy po prostu nazwę zmiennej. Powodem takiego zachowania jest brak nawiasów klamrowych w przypadku pierwszej zmiennej. VSC nie jest w stanie określić, gdzie dokładnie kończy się zmienna, ponieważ znak _ występuje bezpośrednio po jej nazwie (nie ma odstępu).

Rozwiązaniem jest zapisanie zmiennej $TM_FILENAME_BASE w ten sposób: ${TM_FILENAME_BASE}. Teraz dowolny znak może występować bezpośrednio po zmiennej i nadal zostanie ona poprawnie odczytana.

Zmienne w praktyce

Znasz już większość koncepcji potrzebnych, żeby napisać złożony snippet. Przykład, którym się posłużę będzie dotyczyć Reacta, z uwagi na jego popularność. Jeżeli jednak nie korzystasz z tej biblioteki, to nadal zachęcam do zapoznania się z poniższym kodem - możesz dostosować go, do swoich potrzeb.

Większość właściwości powinna być na tym etapie zrozumiała, dlatego skupmy się na body. Cyfry na początku oznaczają których linii dotyczy opis:

  • 7 - importujemy bibliotekę React. Znak \ użyty jest jako escape character

  • 9 - 11 - tworzymy interface nazwie takiej samej, jak nazwa pliku, a następnie dodajemy do niej słowo Props

  • 13-19 - boilerplate komponentu funkcyjnego w React. Nazwa zmiennej odpowiada nazwie pliku (bez rozszerzenia). Parametry (propsy) zostały otypowane przy użyciu interface'u utworzonego powyżej

  • 21 - eksportujemy utworzony komponent (jego nazwa odpowiada nazwie pliku, dlatego w tym miejscu również używamy zmiennej TM_FILENAME_BASE

Zwróć uwagę na wcięcia - musisz dodać je manualnie jeżeli chcesz otrzymać poprawnie sformatowany kod.

Transformacja zmiennych

W niektórych przypadkach dostępne zmienne okażą się niewystarczające i trzeba je będzie dostosować do naszych potrzeb. Z pomocą przychodzą transformatory zmiennych.

Warto wiedzieć o ich istnieniu, jednak nie zalecam uczyć się ich na pamięć. W każdej chwili możesz zajrzeć do dokumentacji, lub wrócić do tego artykułu. W zrozumieniu tematu znacznie pomoże znajomość wyrażeń regularnych, a przynajmniej podstawowa wiedza z tego zakresu.

Pokażę Ci jak wykorzystać transformator na podstawie przykładu, który opiera się na założeniu, że foldery z komponentami oraz pliki, mają dokładnie tą samą nazwę co sam komponent. Plik index.ts eksportuje utworzony komponent, dzięki czemu uzyskujemy prostsze ścieżki w momencie importu.

Przykładowa struktura folderów

src
├── app.tsx
└── components
    └── Footer
        ├── Footer.tsx
        └── index.ts

Snippet, który będziemy tworzyć, to domyślny eskport komponentu z pliku index.ts. Natkiemy się tu na jeden problem - nie możemy posłużyć się zmienna TM_FILENAME_BASE, ponieważ odnosi się ona do nazwy pliku, więc w przypadku index.js, otrzymamy po prostu index. Wynik, który chcemy uzyskać to Footer.

Użyłem zmiennej TM_DIRECTORY w nawiasach klamrowych (jest to konieczne w przypadku wykorzystania transformatorów), a następnie zastosowałem wyrażenie regularne /(.*)\\..+$/ (regex) żeby pobrać nazwę folderu. Ostatni element to użycie zmiennej $1, która w tym miejscu oznacza pierwszą trafioną grupę w zastosowanym wcześniej regexie.

Zapis ten nie jest szczególnie czytelny. Najlepiej będzie rozbić go na poszczególne elementy:

${TM_DIRECTORY/(.*)\\..+$/$1/}
  |            |          |  
  |            |          |  
  |            |          |
  |            |          |-> referencja do pierwszego trafienia
  |            |                w regex
  |            |
  |            |-> regex, znajduje wszystkie trafienia 
  |                           
  |
  |-> ścieżka do aktualnego pliku

Podsumowanie

Możliwość tworzenia własnych snippetów to szansa na zaoszczędzenie znacznej ilości czasu podczas powtarzalnych zadań, a takie w codziennej pracy trafiają się bardzo często. Jeżeli do tej pory nie korzystałeś z tej funkcjonalności, to koniecznie już dzisiaj zdefiniuj swoje pierwsze snippety!

Na sam koniec - nie zachęcam do nauki składni na pamięć (a wręcz odradzam), jednak dobrze jest znać możliwości, jakie oferuje nam Visual Studio Code w tym zakresie. Gdy będziesz pisać swoje własne skrawki kodu, wróć do tego artykułu, lub do oficjalnej dokumentacji.

Avatar: Wojciech Rygorowicz

Software Engineer / Fullstack developer

Wojciech Rygorowicz

wojciech.rygorowicz@gmail.com

Podziel się na

Dodaj komentarz

Komentarze (0)

Brak komentarzy