Unit Sockets - Free Pascal

Unit Sockets - Free Pascal
babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Może trochę przydługi wstęp będzie ale to mój pierwszy post tutaj i jeszcze nie ogarniam wszystkich zasad tego forum.

Piszę grę dla dwóch osób. Gra turowa i dobrze by było gdyby gracze nie widzieli swoich ruchów więc opcja "hot seats" odpada. Zostaje mi tylko przesyłanie danych przez sieć. Żeby uprościć działanie gry założymy że będą to szachy (oczywiście szachy to nie są, co można wywnioskować chociażby z tego że gracze nie powinni widzieć swoich ruchów).

Mamy mapę podzieloną na pola i pionki na mapie na odpowiednich polach. Pierwszy gracz wykonuje ruch i po zakończeniu ruchu chcę, żeby dane z mapy były przesłane do drugiego gracza, następnie on wykona ruch i uaktualnione dane z mapy były wysłane z powrotem do gracza numer 1.

Wybrałem kompilator FPC i to co chce napisać to jest raczej trolling niż programowanie bo do rysowania używam WinGraph znalezionego na necie a grafika to nic innego jak rysowanie bitmap z 256-bitowego obrazka bmp a nie żadne opengl czy directx. Więc jak już troluje to troluje na całego i tu pojawia się moja prośba: Czy ktoś z forumowiczów był by tak miły i opisał unit Sockets wraz z prostymi krótkimi przykładowymi programami? Jak nawiązać połączenie? Jak przesłać dane? Czy muszę przesyłać tylko stringi czy mogą to być dane typu Byte lub całe tablice? Czy jest limit wielkości przesłanych danych? W internecie tego szukałem ale nie mogłem znaleźć opisu "dla idiotów" z przykładowymi prostymi programami. Bardzo bym był wdzięczy za pomoc.

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

Lepszym pomysłem niż użycie dosyć cienkiego sockets, jest użycie Synapse ( http://www.ararat.cz/synapse/doku.php/start i tu http://wiki.lazarus.freepascal.org/Synapse ). Jest ono wieloplatformowe i wspiera wszystko co do sieci normalnym ludziom potrzeba. Jest od niego masa tutków w necie, więc chyba to najlepszy wybór.

Jeżeli mimo wszystko chcesz Sockets to masz tutaj: http://www.freepascal.org/docs-html/rtl/sockets/index.html - powinny gdzieś być przykłady.

@Patryk27, Synapse<>Sockets

babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Uh chyba porwałem się z motyką na słońce... Zobaczę co to to Synapse skoro tak polecacie. W razie jak bym miał jakieś problemy to są tematy na forum odnośnie Synapse bym nie spamował tutaj tylko sobie poczytał?

0

Zobaczę co to to Synapse skoro tak polecacie. W razie jak bym miał jakieś problemy to są tematy na forum odnośnie Synapse bym nie spamował tutaj tylko sobie poczytał?

Przecież dałem już link do tutoriala angielskiego całkiem dobrego do Synapse. Skoro nie znasz ang. to nie licz na jakikolwiek lepszy tutorial (chociaż pewnie pare gdzieś jest), a jeżeli znasz ang. to wpisanie hasła w google nie powinno być dla ciebie problemem.

Uh chyba porwałem się z motyką na słońce...

Od czegoś trzeba zacząć zabawę z socketami. Jeżeli będziesz mieć jakieś konkretne problemy śmiało pytaj spróbuję rozjaśnić problemy z synapse (chociaż za eksperta w tej sprawie się nie uważam). Tylko oczywiście musisz conieco wiedzieć o programowaniu i wykazać inicjatywę w postaci przeszukania googla i poeksperymentowania.

Pare przydatnych linków o synapse:
http://wiki.lazarus.freepascal.org/Synapse - tutek i instalacja pod Lazarusem (warto ściągnąć Lazarusa i go ogarnąć jak się już troche umie kodzić, bo wygląda i działa o niebo lepiej niż IDE FPC a kompilator jest ten sam).
http://synapse.ararat.cz/doc/help/ - Dokumentacja Synapse, osobiście uważam ją za nie specjalnie przydatną, ale czasami warto zajrzeć.
http://www.ararat.cz/synapse/doku.php/public:howto - Tutki o Synapse, bardzo dobrze uczą jeżeli używa się ich do referencji względem dem dołączonych do Synapse.

babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Dobra trochę poczytałem i spłodziłem coś takiego:

Kopiuj
{$MODE DELPHI}
Program Serwer;
Uses Crt,
     blcksock;
Var
  Server : TTCPBlockSocket;
  Buff   : Byte;

Begin
  ClrScr;

  Write ('Czekanie na połaczenie...');
  Server := TTCPBlockSocket.Create;
  Server.Bind('192.168.0.2', '1234');
  If Server.LastError <> 0 Then
  Begin
    Write ('Błąd: ');
    Writeln (Server.LastErrorDesc);
    ReadKey;
    Halt (Server.LastError);
  end;
  Server.Listen;
  Server.Accept;
  Writeln ('Połączono.');
  Writeln;

  Writeln ('Otrzymane dane:');
  Repeat
    Buff := Server.RecvByte (2000);
    Writeln (Buff);
  Until Buff = 0;
  Writeln;
  Writeln ('Koniec');
  Readkey;
end.
Kopiuj
{$MODE DELPHI}
Program Klient;
Uses Crt,
     blcksock;
Var
  Client : TTCPBlockSocket;
  Buff   : Byte;

Begin
  ClrScr;
  Randomize;

  Write ('Łączenie...');
  Client := TTCPBlockSocket.Create;
  Client.Connect('192.168.0.2', '1234');
  If Client.LastError <> 0 Then
  Begin
    Write ('Błąd: ');
    Writeln (Client.LastErrorDesc);
    ReadKey;
    Halt (Client.LastError);
  end;
  Writeln ('Połączono');
  Writeln;

  Writeln ('Wysyłanie');
  Repeat
    Buff := Random (256);
    Writeln (Buff);
    Client.SendByte (Buff);
  until buff = 0;
  Writeln ('Koniec Wysyłania');
  Readkey;
end.

I krótki opis jak to powinno działać oraz jak działa:

  1. Jak powinno działać:

Wiadomo serwer czeka na połączenie, klient próbuje się połączyć. Po połączeniu klient losuje liczby z przedziału od 0 do 255 wypisuje na ekran i wysyła do serwera. Serwer Odbiera liczby i również wypisuje na ekran. Gdy klient wylosuje 0 oba programy kończą pracę.

  1. Jak działa:

Po odpaleniu serwera wyświetla się "Czekanie na połączenie...". No to odpalam klienta. Klient łączy się z serwerem i wypisuje wylosowane liczby ostatnia to "0" i potem następna linijka to "Koniec". A w serwerze (po odpaleniu klienta) wypisuje "Czekanie na połączenie...Połączono", linijka przerwy, "Otrzymane dane:" i po dwóch sekundach (taki timeout) "0" linijka przerwy i "Koniec".

Jakaś interakcja między dwoma programami jest ale albo klient nie wysyła danych, albo serwer ich nie odbiera. Żeby nie było problemów to firewalla i antywirusa wyłączyłem całkowicie bo myślałem, że te programy coś blokują ale to nic nie dało. Wersje FPC mam 2.4.0 a synapse 39 (przynajmniej tak była oznaczona na stronie). Ja coś źle zrobiłem czy za stary kompilator na tą wersje synapse lub lipne synapse?

edytowany 1x, ostatnio: babubabu
0

Ja coś źle zrobiłem czy za stary kompilator na tą wersje synapse lub lipne synapse?

Coś skopałeś, nawet wiem co.

Server.Accept; - to zwraca socket za pomocą którego komunikujesz się z klientem. Socket servera służy tylko do odbierania połączeń. Do wysyłania/odbierania danych od klientów służy właśnie ten socket który otrzymujesz z accept (jest on już otwarty,po prostu robisz na nim to co chcesz).

Jeszcze taka mała uwaga: Generalnie niewiele robi się tego typu protokołów gdzie każdy pakiet ma jeden bajt, ja bym spróbował nakodzić coś co wysyła między sobą stringi, byłoby bardziej życiowe :) . Ale też trudniejsze, więc jak na pierwszy raz i tak wypadłeś ponadprzeciętnie :P

babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Server.Accept; - to zwraca socket za pomocą którego komunikujesz się z klientem. Socket servera służy tylko do odbierania połączeń. Do wysyłania/odbierania danych od klientów służy właśnie ten socket który otrzymujesz z accept (jest on już otwarty,po prostu robisz na nim to co chcesz).

Ok rozumiem. W dokumentacji doczytałem, że accept to jest funkcja i zwraca dane typu TSocket. Wszystko fajnie tylko co mam zrobić z tą wartością? I co to dokładnie jest za wartość? Bo tak jak przeglądam dokumentacje i googluje o synapse to jedyne co zaobserwowałem to wywołanie accept jak procedury bez przypisania wyniku do czegokolwiek. Na tą chwilę jedyne co wymyśliłem to takie cuś:

Kopiuj
 
// program uses itp.
var
  Server : TTCPBlockSocket
  Dane : TTCPBlockSocket

Begin
  // Obsługa socketu Server i ustanowienie połączenia
  Dane := Server.Accept;
  Buff := Dane.RecvByte (2000);
  // Reszta programu
end.

Ewentualnie przed:

Kopiuj
 
Buff := Dane.RecvByte (2000);

Można jeszcze wcisnąć:

Kopiuj
 
Dane := TTCPBlockSocket.Create;

albo jeszcze wcześniej przed accept.

Jednak dzisiaj już późno więc przetestuje to rozwiązanie jutro i podzielę się wynikiem.

Jeszcze taka mała uwaga: Generalnie niewiele robi się tego typu protokołów gdzie każdy pakiet ma jeden bajt, ja bym spróbował nakodzić coś co wysyła między sobą stringi, byłoby bardziej życiowe :) . Ale też trudniejsze, więc jak na pierwszy raz i tak wypadłeś ponadprzeciętnie :P

To co napisałem to tylko próba ogarnięcia i poznania zasady działania synapse, więc wybrałem najprostszą metodę :) Jak zrozumiem o co chodzi to pobawię się stringami bo z tego co pamiętam to w mojej grze będę musiał przesłać około 700 bajtów danych więc robić z tego 700 pakietów jest bez sensu szczególnie, że pakiet może mieć 1kB więc wszystko mogę zmieścić w jednym pakiecie ewentualnie w dwóch, więc jeśli dobrze zrozumiałem to co czytałem o przesyłaniu danych to przesłanie jednego pakietu jest 700 razy szybsze niż przesłanie 700 pakietów :)

edytowany 4x, ostatnio: babubabu
0

Bo tak jak przeglądam dokumentacje i googluje o synapse to jedyne co zaobserwowałem to wywołanie accept jak procedury bez przypisania wyniku do czegokolwiek

O to bardzo ciekawe bo to bez sensu jeżeli chcemy coś zrobić z klientem który się do nas podłączył. Pierwszy kod który dałeś jest poprawny, po akceptacji połączenia odbierze on od niego dane. Najlepiej wtedy zamknąć też Socket czekający na połaczenia o ile nie chcesz więcej połączeń.

Jak zrozumiem o co chodzi to pobawię się stringami bo z tego co pamiętam to w mojej grze będę musiał przesłać około 700 bajtów danych więc robić z tego 700 pakietów jest bez sensu szczególnie, że pakiet może mieć 1kB więc wszystko mogę zmieścić w jednym pakiecie ewentualnie w dwóch, więc jeśli dobrze zrozumiałem to co czytałem o przesyłaniu danych to przesłanie jednego pakietu jest 700 razy szybsze niż przesłanie 700 pakietów

Jak się domyślam, to Synapse nie fluszuje tego Od razu, więc robią się grupki tych bajtów, nie chodziło mi o pakiety w rozumieniu czysto TCP.
Czas przesłania pakietu jest generalnie taki sam póki jest on jednoczęściowy (czyli wysyłany na raz), przy czym może on zostać spowolniony jeżeli w danym momencie nie ma jak go wysłać. Generalnie o ile gra nie wymaga tych pakietów superszybko nie musisz się specjalnie martwić o pakiety itd., bo grunt to żeby to wysłać i odebrać.

babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Ale jestem z siebie dumny :)

Kopiuj
 
Server.Socket := Server.Accept;

Załatwiło sprawę i wszystko działa :)

Pierwszy kod który dałeś jest poprawny, po akceptacji połączenia odbierze on od niego dane.

I nie jest poprawny :) poczytałem wymyśliłem i działa :)

Przetestuje to teraz na dwóch oddzielnych komputerach. Jak będzie działać to wysyłanie danych z klienta do serwera ogarnięte :) Zostanie tylko wysyłanie z serwera do klienta. A jak to ogarnę to zajmę się stringami :)

@Edit
Dobra ogarnięte wszystko. Poniżej źródła dwóch programów (serwer,klient). Klient przesyła do serwera to co wpiszemy z klawiatury a serwer to wyświetla.

Serwer:

Kopiuj
 
{$MODE DELPHI}
Program Serwer;
Uses Crt,
     blcksock;
Var
  Server : TTCPBlockSocket;
  Buff   : String;

Begin
  ClrScr;

  Write ('Czekanie na połaczenie...');
  Server := TTCPBlockSocket.Create;
  Server.Bind('192.168.0.2', '1234');
  If Server.LastError <> 0 Then
  Begin
    Write ('Błąd: ');
    Writeln (Server.LastErrorDesc);
    ReadKey;
    Halt (Server.LastError);
  end;
  Server.Listen;
  Server.Socket := Server.Accept;
  Writeln ('Połączono.');
  Writeln;

  Writeln ('Otrzymane dane:');
  Repeat
    Buff := Server.RecvString (10000);
    Writeln (Buff);
  Until buff = '';

Klient:

Kopiuj
 
{$MODE DELPHI}
Program Klient;
Uses Crt,
     blcksock;
Var
  Client : TTCPBlockSocket;
  Buff   : String;

Begin
  ClrScr;

  Write ('Łączenie...');
  Client := TTCPBlockSocket.Create;
  Client.Connect('192.168.0.2', '1234');
  If Client.LastError <> 0 Then
  Begin
    Write ('Błąd: ');
    Writeln (Client.LastErrorDesc);
    ReadKey;
    Halt (Client.LastError);
  end;
  Writeln ('Połączono');
  Writeln;

  Writeln ('Napisz co wysłać (pusta linia zakończy prace programu):');
  Repeat
    Readln (Buff);
    Buff := Buff + CRLF;
    Client.SendString (buff);
  Until buff = ''+CRLF;
end.

Dzięki za pomoc :) Jak bym miał jeszcze jakieś problemy związane z synapse to zapytam tutaj, a jak skończę grę to się pochwalę :)

edytowany 3x, ostatnio: babubabu
0

I nie jest poprawny poczytałem wymyśliłem i działa

No właśnie jest, a twój nie...

Ten kod co dałeś to jest piękny przykład że to że działa nie znaczy że jest dobrze. Twój kod powoduje wyciek pamięci na dodatek powoduje on to że port ciągle będzie zbindowany a socket ciągle będzie oczekiwać połączenia.

Weź jakoś tak to napisz jak to ludzie robią:

Kopiuj
var
server:TTCPBlockSocket;
server_cl:TSocket;

[...]
server_cl:=server.Accept;
FreeAndNil(server);
[tutaj sobie odbierasz za pomocą server_cl]
babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Dobra nie rozumiem o co Ci chodzi.
Po wpisaniu

Kopiuj
server_cl:TSocket; 

wywala dwa błędy Identifier not found "TSocket" oraz Error in type definition
Zupełnie nie wiem też o jaki wyciek chodzi no i jak wywalę obiekt socketa z pamięci to się zaczną Runtime errory.

edytowany 1x, ostatnio: babubabu
1

Dodaj sobie moduły synsock,sysutils, ja je mam i mi widzi TSocket.

Zupełnie nie wiem też o jaki wyciek chodzi

Wyciek pamięci, masz niezwolniony obiekt do którego nie masz żadnej referencji.

no i jak wywalę obiekt socketa z pamięci to się zaczną Runtime errory.

A to z jakiej racji?!

babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Dobra z tego co zrozumiałem to by wysłać lub odebrać dane to wywołuje odpowiednie funkcje obiektu czy to serwer czy client (Serwer.SendCosTam, Client.RecvCosTam) Więc co mi po samym numerku z accept skoro to nie jest obiekt który wysyła/dobiera? Ewentualnie jeśli sam numer jest do czegoś potrzebny to do czego i jak go wykorzystać?

A żeby nie było żadnego wycieku to na końcu programu wystarczy dodać Client.Free, Server.Free?

0

Ah mój błąd nie doczytałem wczoraj co trzeba zrobić z TSocket :) Ale widzę że doszedłeś podobnie tylko że u ciebie gubi się oryginalna referencja.

Kopiuj
var
server,server_cl:TTCPBlockSocket;
temp:TSocket;

begin
[blabla oczekiwanie na polaczenie]
temp:=server.Accept;
server_cl:=TTCPBlockSocket.Create();
server_cl.socket:=temp;
FreeAndNil(server);//Już nam oczekiwanie na połączenia nie potrzebne
[teraz sobie gadasz z clientem na server_cl].
FreeAndNil(server_cl);//Zwalniamy grzecznie klasę gdy już nie potrzebna.

A żeby nie było żadnego wycieku to na końcu programu wystarczy dodać Client.Free, Server.Free?

http://4programmers.net/Forum/Delphi_Pascal/97741-Pamiec_-_zwalnianie_i_wycieki -tutaj troche powiedzieli jak się zwalnia klasy.

Generalnie to musisz rozumieć zasadę działania klas i to że definicja a:TKlasa nie tworzy obiektu ale jest jedynie referencją. Potem sobie tworzysz konstruktorem klasę i odnośnik do niej zapisujesz w przykładowo a. Jeżeli zrobisz a:=nil; to nie będzie wiadomo gdzie jest ta klasa więc nie będziesz mógł jej zwolnić, więc zanim zmienisz ten odnośnik na coś innego trzeba zwolnić klasę np. a.Free; albo FreeAndNil(a);. Druga metoda przypisze też do a NIL.
A co się działo w twoim kodzie? Gubiłeś odnośnik do oryginalnego socketa nie zwalniając go w wyniku czego czekał ciągle na połączenie i blokował port. Z tego co teraz widzę nie spowodowałby on wycieku pamięci ale zablokowałby port. Więc najlepiej zwalniać obiekty gdy nie są potrzebne, a już na 100% trzeba zadbać o to żeby nie zgubić do niego referencji bo to by powodowało problemy gdy twój kod zrobi tak milion razy (zapchałbyś pamięć = crash/lag).

babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

Po przeczytaniu tego

Kopiuj
 
[blabla oczekiwanie na polaczenie]
temp:=server.Accept;
server_cl:=TTCPBlockSocket.Create();
server_cl.socket:=temp;
FreeAndNil(server);

Zatrybiłem o co Ci chodzi :) I nawet zrozumiałem mój błąd :) resztę przeczytałem z Ciekawości i co to konstruktor oraz destruktor to wiem , podstawowe pojęcia znam. Dzięki za pomoc na pewno zamieszczę to w kodzie :)

Mam tylko jedno pytanie. Czy konieczne jest tworzenie zmiennej temp, nie lepiej od razu napisać server_cl.socket := server.Accept?

edytowany 2x, ostatnio: babubabu
0

Mam tylko jedno pytanie. Czy konieczne jest tworzenie zmiennej temp, nie lepiej od razu napisać server_cl.socket := server.Accept?

Nie jest konieczne ale ja tak mam w swoich kodach bo po Accept sprawdzam czy server.LastError=0 na wypadek błędu zanim jeszcze to przypisze do socketa. Więc jak nie chcesz tego sprawdzać na wypadek błędu to oczywiście nie trzeba.

Pamiętaj że jeżeli rozwiązałem problem to żeby oznaczyć post który go rozwiązał 'ptaszkiem', taka dziwota tego forum.

babubabu
  • Rejestracja:około 13 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Łódź
  • Postów:648
0

No to wszystkie twoje posty poptaszkuje :)

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)