Indexed property – problem z modyfikacją pola rekordu

Indexed property – problem z modyfikacją pola rekordu
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Chcę sobie napisać rekord, który jednocześnie będzie jakby dynamiczną tablicą rekordów, obudowaną w funkcje i nie mogę sobie poradzić z uzyskaniem właściwego rezultatu.

Kopiuj
type
  TCell = record
    Value: Integer;
  end;

  TList = record
  strict private
    ConCell: array of TCell;
    function GetCell(Index: Integer): TCell;
    property Cell[Index: Integer]: TCell read GetCell; default;
  public
    procedure SetSize(pSize: Integer);
    procedure Clear;
  end;

var
  List: TList

=====

function TList.GetCell;
begin
  Result:= ConCell[Index];
end;

Dzięki takiej konstrukcji mogę raz "zarządzać" całą listą i np. chcąc ją wyczyścić albo zmienić jej wielkość, robię tak:

Kopiuj
List.Clear;
List.SetSize(4);

A potem chcąc uzyskać dostęp do poszczególnych komórek listy, robię tak:

Kopiuj
JakasZmiena:= List[0].Value;

zamiast:

Kopiuj
JakasZmienna:= List.ConCell[0].Value;

Teoretycznie niewiele, ale to eleganckie rozwiązanie :). Sęk w tym, że to działa tylko przy odczycie i nie wiem jak to zakodować tak, żeby pozwoliło mi także zapisywać poszczególne zmienne w komórkach. Właściwość PropCell jako metodę zapisu (write) łyknie tylko coś takiego (z uwagi na zgodność typów):

Kopiuj
procedure SetCell(Index: Integer; pCell: TCell);

Ale to odpada, bo w ten sposób mogę tylko przypisywać całe komórki, np.:

Kopiuj
List[0]:= JakasKomorka; //JakasKomorka to zmienna typu TCell

Na coś takiego już mi nie pozwoli:

Kopiuj
List[0].Value:= 167;

Da się to jakoś obejść?

edytowany 12x, ostatnio: flowCRANE
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
0

Niestety nie, jest to ograniczenie tej składni.


flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Tuchów
  • Postów:12155
1

Jak wspomniał @Patryk27, jest to ograniczenie języka, ale da się to rozwiązać dodając właściwość do struktury TCell. Bo w takim przypadku musi być użyta właściwość, a nie pole.

Nie musi ona posiadać settera w postaci metody – wystarczy bezpośredni dostęp do pola.

Przykład deklaracji:

Kopiuj
type
  TItem = record
  private
    FData: Integer;
  public
    property Data: Integer read FData write FData;
  end;

type
  TList = record
  private
    FList: array [0..3] of TItem;
  private
    function GetItem(AIndex: Integer): TItem;
    procedure SetItem(AIndex: Integer; AItem: TItem);
  public
    property Items[AIndex: Integer]: TItem read GetItem write SetItem; default;
  end;

  function TList.GetItem(AIndex: Integer): TItem;
  begin
    Result := FList[AIndex];
  end;

  procedure TList.SetItem(AIndex: Integer; AItem: TItem);
  begin
    FList[AIndex] := AItem;
  end;

I przykład użycia:

Kopiuj
var
  List: TList;
begin
  List[0].Data := 10; // składnia dozwolona
end.

To powoduje, że właściwość TItem.Data umożliwia aktualizowanie danych struktury pojedycznej pozycji, a właściwość TList.Items pozwala odczytywać i modyfikować całe rekordy pozycji.

W powyższym przykładzie posłużyłem się macierzą o statycznym rozmiarze, żeby nie zaśmiecać przykładowego kodu informacjami, których problem nie dotyczy.


Pytanie dodatkowe – dlaczego bawisz się rekordami, zamiast skorzystać z gotowego kontenera, np. TList?


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 10x, ostatnio: flowCRANE
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Gdy korzystam z twojego przykładu, to wywala mi błąd: E2064 Left side cannot be assigned to

A dlaczego nie użyję TList? Bo to był tylko zmyślony przykład :). Tak na prawdę mam rekord, który grupuje powierzchnie ("Faces") i ma kilka wbudowanych metod do grupowej obsługi tych powierzchni. Czasem jednak potrzebna jest ingerencja indywidualna. Grupowo używam tego tak:

Kopiuj
Faces.ReadNormals;

A indywidualnie tak:

Kopiuj
Faces.Face[13].ReadNormal;

No i pomyślałem sobie, że fajnie by było móc to skrócić i pisać tak:

Kopiuj
Faces[13].ReadNormal;
edytowany 7x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Tuchów
  • Postów:12155
0

Kod testowałem pod Lazarusem i działa prawidłowo. ;)

Crow napisał(a):

A indywidualnie tak:

Kopiuj
Faces.Face[13].ReadNormal;

No i pomyślałem sobie, że fajnie by było móc to skrócić i pisać tak:

Kopiuj
Faces[13].ReadNormal;

No tak, tyle że to jest samo ukrycie właściwości (?) Face, a to robi się za pomocą default. No to jak w końcu, chodzi o stworzenie właściwości domyślnej, czy dodaniu możliwości modyfikacji poszczególnych pól struktur?


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 2x, ostatnio: flowCRANE
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Chodzi o możliwość pełnego korzystania z zawartości rekordu TFace (czyli zapis i odczyt pól, wywoływanie metod), znajdującego się - w formie tablicy - wewnątrz rekordu TFaces, z jednoczesnym ukryciem odwoływania się do niego, czyli np.:

Kopiuj
TFace = record
  Value: Integer;
  Low: Double;
  Metoda1
end;

TFaces = record
strict private
  CFace: array of TFace;
  function GetFace(Index: Integer): TFace;
  procedure SetFace(Index: Integer; TFace);
  property Face[Index: Integer]: TFace read GetFace write SetFace; default;
public
  Metoda1;
  Metoda2;
end;

Użycie:

Kopiuj
Faces[123].Value:= 76;
Zmienna:= Faces[14].Low;
Faces[16].Metoda1;

zamiast

Kopiuj
Faces.Face[123].Value:= 76;
Zmienna:= Faces.Face[14].Low;
Faces.Face[16].Metoda1;

A co do twojego kodu, to zrobiłem kopiuj / wklej i wyskakuje wspomniany błąd :(.

edytowany 5x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Tuchów
  • Postów:12155
1
Crow napisał(a):

Chodzi o możliwość pełnego korzystania z zawartości rekordu TFace (czyli zapis i odczyt pól, wywoływanie metod), znajdującego się - w formie tablicy - wewnątrz rekordu TFaces, z jednoczesnym ukryciem odwoływania się do niego […]

W dalszym ciągu nie wiem dlaczego używasz rekordów i dlaczego sam implementujesz listę (w dodatku w postaci rekordu), zamiast skorzystać z klasy (do opisu pojedynczej ”twarzy”) oraz z wbudowanego generycznego kontenera pokroju TList (do przechowywania listy tych ”twarzy”). Dorobiłbyś sobie settery i mógłbyś modyfikować co tylko chcesz, nawet pojedynczo, i też mógłbyś mieć domyślne indeksowane właściwości.

Robisz tak dlatego, że pracujesz nad jakimś tam projektem i nie możesz tego zmienić, czy z innego powodu?

A co do twojego kodu, to zrobiłem kopiuj / wklej i wyskakuje wspomniany błąd :(.

Widać FPC w tym przypadku różni się od Delphi, pozwalając na taką konstrukcję. Innego rozwiązania nie znam.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 6x, ostatnio: flowCRANE
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Nie zmieniam na TList, bo cały projekt zbudowałem na bazie tablic i teraz nie chce mi się wszystkiego przerabiać :). Może w następnej wersji projektu spróbuję. Tak czy inaczej dzięki! ;].

edytowany 1x, ostatnio: flowCRANE
flowCRANE
Nie cytuj całego posta, jeśli odpowiadasz zaraz pod nim i do jego całości się odnosisz – wątek niepotrzebnie się rozciąga. :P
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Jednak muszę odkopać (przepraszam), bo coś nie działa...

Kopiuj
TFace = record
  Value: Integer;
end;

TFaces = class(TList<TFace>)
  //Jakies metody
end;

var
  F: TFace;
  Faces: TFaces;

Faces:= TFaces.Create;
F.Value:= 0;
Faces.Add(F);
Faces[0].Value:= 123;

Dostaję error:

Kopiuj
E2064 Left side cannot be assigned to

Próbowałem też dodać do TFace właściwość. Bezpośrednie wskazanie na zmienną stanowiącą kontener (read cValue write cValue) dawało ten sam error, skompilowało się dopiero po dodaniu gettera i settera... tyle, że całość nadal nie działa i zmienna się nie nadpisuje.

Kopiuj
procedure TFaces.SetValue(pValue: Integer);
begin
  cValue:= pValue; //cValue to zmienna kontenera, z której odczytuje i do której zapisuje właściwość Value;
end;

Faces:= TFaces.Create;
F.Value:= 0;
Faces.Add(F);
Face[0].Value:= 123; //kompiluje się ale nadal jest tam zero

Działa tylko coś takiego:

Kopiuj
Faces:= TFaces.Create;
F.Value:= 0;
Faces.Add(F);
F.Value:= 100;
Faces[0]:= F;

No ale coś takiego mnie nie urządza, bo ja chcę indywidualnego dostępu do pól rekordu, bez każdorazowego nadpisywania całego rekordu.

edytowany 9x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Tuchów
  • Postów:12155
1
Crow napisał(a):

Dostaję error:

Kopiuj
E2064 Left side cannot be assigned to

To jest ten sam problem co wcześniej – jeśli właściwość zwraca rekord, to nie możesz modyfikować jego pól bezpośrednio. Analogicznie do mojego poprzedniego przykładu, spróbuj w taki sposób:

Kopiuj
type
  TItem = record
  private
    FData: Integer;
  public
    property Data: Integer read FData write FData;
  end;

type
  TList = class(TList<TItem>);

i użycie:

Kopiuj
var
  List: TList;
  Item: TItem;
begin
  List := TList.Create();
  
  Item := TItem.Create();
  Item.Data := 10;
  
  List.Add(Item);
  List[0].Data := 20; // sprawdź czy działa

Jeśli działa to popraw swój kod, a jak nie to wymień rekordy na zwykłe, poste klasy. A jeśli potrzebujesz typu zarządzanego, alokowanego na stosie, to spróbuj w podobny sposób wykorzystać stare obiekty.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 2x, ostatnio: flowCRANE
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Dokładnie tak samo próbowałem to rozwiązać, ale nie działa. Na szczęście udało się z klasami prostymi, z którymi, z jakiegoś powodu nie ma problemu. Wszystko się kompiluje, a wartości zostają nadpisane poprawnie (nawet nie muszę używać właściwości, zwykłe pola wystarczą). Dzięki, zobaczę w praniu, czy wszystko zadziała jak należy :).


Edit: A jednak nie ;/.

Kopiuj
type
  TFace = class(TObject)
    class var Value: Integer;
  end;

  TFaces = class(TList<TFace>)
    //Jakies metody
  end;

Faces:= TFaces.Create;
  Face.Value:= 0;
  Faces.Add(Face);
  Faces.Add(Face);
  Faces[0].Value:= 123;
  Faces[1].Value:= 345;
  ShowMessage(IntToStr(Faces[0].Value));
  ShowMessage(IntToStr(Faces[1].Value));

Zwraca dwa razy 345, czyli przypisanie do obojętnie którego elementu listy, nadpisuje całą :(.

edytowany 6x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Tuchów
  • Postów:12155
0

@Crow: wiesz w ogóle czym są zmienne klasowe? Raczej nie…

Miałeś skorzystać ze zwykłej klasy, w której byłoby prywatne pole i publiczna właściwość:

Kopiuj
type
  TFace = class(TObject)
  private
    FValue: Integer;
  public
    property Value: Integer read FValue write FValue;
  end;

albo od biedy publiczne pole bez właściwości, jeśli jakakolwiek walidacja itp. nie jest potrzebna:

Kopiuj
type
  TFace = class(TObject)
  public
    Value: Integer;
  end;

Takie pola są unikalne dla każdej instancji (obiektu), więc modyfikacja danych jednego obiektu nie spowoduje zmiany danych w innych obiektach tej samej klasy. Druga istotna rzecz to to, że nie ma dostępu do tych pól przez utworzeniem instancji klasy, a po jej utworzeniu można te dane modyfikować tylko za pomocą referencji. Czyli tak:

Kopiuj
var
  Face: TFace;
begin
  Face := TFace.Create();
  Face.Value := 100; // zmiana wartości

Zmienne klasowe to zupełnie inna bajka. Te przynależą do klasy i są wspólne dla klasy oraz wszystkich jej instancji. Istotny jest właśnie ten fakt – zmienna należy do klasy, a jej wartość można modyfikować za pomocą referencji, czyli tak:

Kopiuj
type
  TFace = class(TObject)
    class var Value: Integer;
  end;

var
  Face: TFace;
begin
  Face := TFace.Create();
  Face.Value := 100; // zmiana wartości

ale też za pomocą samego identyfikatora klasy (bez konieczności tworzenia instancji):

Kopiuj
type
  TFace = class(TObject)
    class var Value: Integer;
  end;

begin
  TFace.Value := 100; // zmiana wartości

Twój kod działa prawidłowo, dlatego że zmienna klasowa jest jedna, bez względu na liczbę utworzonych referencji. Modyfikując jej wartość sprawiasz, że nowa wartość dostępna jest z poziomu dowolnego elementu listy i jest taka sama.


Podsumowując, nie używaj rzeczy, których przeznaczenia nie rozumiesz i nie kombinuj, jeśli nie potrzebujesz. A po drugie, zanim użyjesz nowego elementu lub konstrukcji, najpierw kuknij do dokumentacji i zapoznaj się z jego/jej specyfiką, bo programowanie randomowe to z reguły bardzo zły pomysł. ;)


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 7x, ostatnio: flowCRANE
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Dzięki za odpowiedź. A co do kombinowania, to właśnie w taki sposób uczę się nowych rzeczy :) (jak kiedyś pisałem, nie jestem programistą tylko humanistą ;p). Testuję -> nie działa -> próbuję rozwiązać problem -> profit :). No ale to chyba raczej nie zadziała, bo nijak nie jestem w stanie uzyskać dostępu do zmiennej Value wewnątrz TFace poprzez Faces[Index].Value. Przy próbie korzystania z właściwości, ciągle wywala mi ten sam błąd E2064 Left side cannot be assigned to, niezależnie czy używam domyślnego TList, własnego TList, czy tablic. W Lazarusie to może działa, w Delphi niestety nie ;/.

edytowany 1x, ostatnio: Crow
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Tuchów
  • Postów:12155
2

Użyj generycznego TObjectList:

Kopiuj
type
  TFaces = TObjectList<TFace>;

Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
CR
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 miesięcy
0

Tak, w przypadku klas kompilator się już nie pluje i można je normalnie nadpisywać, nawet bez użycia właściwości. Czyli to było problemem, wystarczyło zamienić rekord na klasę. Dzięki! :).

edytowany 1x, ostatnio: Crow
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)