Od kilku tygodni bawię się po trochu CURLem, w ramach tworzenia PeHaPowej biblioteki do Blip!a. Poniżej kilka zagwozdek, na które ciężko znaleźć sensowną odpowiedź w google, albo ja nie wiem jak pytać…

  1. Jak poprawnie wykonać zapytanie PUT? (aka: metoda PUT i “select/poll returned error”)

    Nad tym spędziłem najwięcej czasu. Kombinowałem na mnóstwo sposobów. Kluczem do sukcesu okazało się podejrzenie wersji konsolowej CURLa z dokładnie takim samym zapytaniem, jakie wysyłałem za pomocą skryptu PHP. W skrócie: należy wymusić na CURLu HTTP 1.0, za pomocą ustawienia opcji:

    curl_setopt ($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); # gdzie $ch jest obiektem utworzonym za pomocą curl_init ()

    Po tej operacji zapytania śmigają jak należy (dodam tylko, że czasem zamiast “select/poll returned error” dostawałem “connection reset by peer”).

  2. Przy rozwiązywaniu powyższego problemu, pomogła mi mała sztuczka. Mianowicie musiałem podejrzeć jakie nagłówki wysyła CURL. Normalnie PHPowy CURL nie zamierza pokazać co jest wysyłane i odbierane (Rozpisałem się - oczywiście nagłówki odbierane bez problemu można zobaczyć. Dzięki, Arek ;) ), bo i po co… Ja posłużyłem się tutaj specjalnie na tą okazję utworzonym skryptem PHP z dokładnie wyizolowanym ‘testcase’. Tutaj, po zaimplementowaniu opcji:

    curl_setopt ($ch, CURLOPT_VERBOSE, 1);

    i odpaleniu skryptu z konsoli, grzecznie została mi pokazana komunikacja wychodząca z serwerem, co było kluczem do rozwiązania problemu (okazało się że był wysyłany dodatkowy nagłówek Expect należący do HTTP 1.1, a po wrzuceniu tego w google znalazłem informacje które mnie nakierowały na właściwy trop).

  3. Jak wysłać plik POSTem?

    Ech, w sumie rozwiązanie jest banalne, jeśli ktoś dokładniej przeczyta manual na stronach PHP dotyczący CURLa. Ale skoro już opisuję zagwozdki…

    PHPowy CURL pozwala wysyłać dane na dwa sposoby (akceptowane i sprecyzowane, oczywiście, w odpowiednim RFC). Jeden to x-www-form-urlencoded (tak są wysyłane dane za pomocą webowych formularzy), drugi to multi-part form-data (tak są wysyłane pliki, także z formularzy). Normalnie dla opcji CURLOPT_POSTFIELDS podaje się string który wygląda dokładnie tak samo jak ten widoczny w URLach skryptów pehapowych (mówiąc po laicku), np. a=1&b=2 - wtedy dane są wysyłane metodą x-www-form-urlencoded. Aby zmusić CURLa do wysłania danych metodą multi-part form-data, jako parametr opcji CURLOPT_POSTFIELDS musimy podać tablicę. Tak, właśnie tablicę, gdzie kluczem powinne być nazwa pola (odpowiadająca temu z prawdziwego formularza), a wartością ścieżka do pliku, ale uwaga: ścieżka powinna być poprzedzona znakiem “małpy”: @. Czyli powinno wyglądać to tak:

    curl_setopt ($ch, CURLOPT_POSTFIELDS, array ('pole' => '@/sciezka/do/pliku.jpg'));

    Po tej operacji wysłanie pliku nie powinno być już problemem :)


Jako, że od jakiegoś czasu zajmuję się perlem, to zależy mi na wynajdywaniu różnych użytecznych sztuczek i/lub informacji dotyczących tego języka. Poniżej zbiór kilku różnych porad, które jakoś się w ostatnim czasie uzbierały :)

  1. ciekawostka: używanie konstrukcji while-each do iteracji po elementach hasza jest wolniejsze niż używanie pary for-keys! Zrobiłem sobie jakiś czas temu do tego prostego benchmarka. Różnica prędkości nie jest duża, wacha się w granicach błędu (3-4%), ale zawsze jest to coś, tym bardziej, że for-keys pozwala na przeiterowanie po elementach hasza w jakiejś dowolnej, określonej przez nas kolejności :)
  2. często jest tak, że jakaś funkcja zwraca nam tablicę elementów, a my potrzebujemy tej referencji do tej tablicy. najprostszym, i do niedawna najczęściej przeze mnie używanym sposobem było zrobienie:
    @$ref = funkcja_zwracajaca_tablice();

    Od niedawna, używam konstrukcji:

    $ref = [funkcja_zwracajaca_tablice()];

    wzrost prędkości sięga nawet 40%!

  3. Powyższa reguła dotyczy także haszy, czyli nie:
    %$ref = funkcja_zwracajaca_hasz();

    tylko

    $ref = {funkcja_zwracajaca_hasz()};
  4. tutaj taki ogólny tips: po co duplikować kod, pisząc:
    $var1 = ($var2 eq 'aaa') ? 1 : 0;

    skoro można zapisać to w skrócie:

    $var1 = ($var2 eq 'aaa');

    ? Bardzo często spotykam się z takim bzdurnym zapisem jak ten pierwszy - pamiętaj że narzuca to dodatkowe wykonanie warunku…

  5. Uwielbiam w perlu prawostronne warunki/pętle. Po prostu strasznie upraszczają zapis, zwiększając przy tym czytelność (oczywiście wszystko jest łatwo nadużyć, ale to osobna kwestia). Przy pętlach brakowało mi strasznie możliwości iterowania z jakimś warunkiem, i wykonania jakiejś akcji gdy warunek jest spełniony. Jak zwykle niezastąpiony bochen znalazł i na to radę:
    ($_%2) and $_ foreach (1..6);

    Co prawda powyższy zapis łatwo zastąpić grepem, ale nie zawsze potrzebujemy otrzymać tablicę wartości, czasem trzeba tylko wykonać jakąś akcję :)

  6. Spotykałem się czasem z problemem przekazywania nazwy funkcji, jaką trzeba wykonać, w zmiennej. Nie zawsze można przekazać referencję do tej funkcji, a na pewno nie zawsze jest to najwygodniejsze co możemy użyć. No i oczywiście pomijam tutaj użycie evala. Metody na rozwiązanie tego problemu są dwie, przy czym preferuję drugą, gdyż nie ponosimy przy tym ryzyka wystąpienia jakichś błędów przy wyłączonym “strict refs”.
    sub test { print 'testujemy'; }
    my $t = 'test';
    • {
          no strict "refs";
          &{$test}();
      }
    • &{*fn = $test}();

    Należy jednak pamiętać że metoda “z globem” jest nawet do 30% wolniejsza od wersji z “no strict refs” (20% jeśli włączymy zaraz na początku wywoływanej w ten sposób funkcji “use strict refs”).

Jeśli macie jeszcze jakieś ciekawostki związane z perlem, to poproszę o linki/konkrety w komentarzach :)


Jak skopiować jakiś tekst z jednego otwartego pliku do drugiego?

Dodaj w .vimrc:

if has("unix")
  nmap xr   :r $HOME/.vimxfer<CR>
  nmap xw   :'a,.w! $HOME/.vimxfer<CR>
  vmap xr   c<esc>:r $HOME/.vimxfer<CR>
  vmap xw   :w! $HOME/.vimxfer<CR>
else
  nmap xr   :r ~/.vimxfer<CR>
  nmap xw   :'a,.w! ~/.vimxfer<CR>
  vmap xr   c<esc>:r ~/.vimxfer<CR>
  vmap xw   :w! ~/.vimxfer<CR>
endif

Teraz, po zaznaczeniu tekstu, wciśnij ‘xw’ aby go zapisać, przejdź do pliku gdzie chcesz dany tekst wstawić, i wciśnij ‘xr’.

Teoretycznie, można używać po prostu kopiowania (yank) za pomocą komendy ‘y’, ale ma ona istotne ograniczenia:

  • pozwala na skopiowanie maksymalnie 50 linii
  • żeby działało, trzeba otworzyć plik z którego chcesz skopiować treść, zamknąć go, otworzyć drugi, wkleić (czy też operacje na buforachw jednym oknie etc. Metoda z ‘xr’ i ‘xw’ pozwala na przenoszenie treści pomiędzy zupełnie różnymi oknami (korzysta z zewnętrznego pliku).

Jak zmienić tekst/słowo/linię na pisane WIELKIMI literami lub na pisane małymi literami? Służy do tego komenda ‘U’ lub ‘u’.

Aby zmienić całą linię na pisaną wielkimi literami: gUU

Aby zmienić całą linię na pisaną małymi literami: guu

Aby zmienić słowo na pisane wielkimi literami: gUaw

Aby zmienić słowo na pisane małymi literami: guaw

Aby zmienić linię na pisaną duzymi literami poczynając od miejsca w którym stoi kursor: gU$

Etc…

Vim ułatwia też zamienianie wielkości liter z małych na duże i odwrotnie - służy do tego znak tyldy (~). Aby zmienić znak na którym stoi kursor, wystarczy wcisnąć tyldę. Aby zamienić wielkość liter na trzech najbliższych znakach, wciskamy: 3~. Reszta - j.w.

Wszystkie polecenie wykonujemy w trybie komend.


W wielu edytorach tekstu mamy możliwość zaznaczenia pewnej linii, i skoku do niej w dowolnym momencie. Vim także posiada taką możliwość.

Oznaczanie linii (mark) wykonuje się poprzez komendę (zaskakujące) ‘mark’ lub w skrócie ‘m’. W linii, której chcesz zaznaczyć, wyjdź do trybu poleceń (<Esc>:), wprowadź ‘mX’, gdzie X jest kolejną małą literą alfabetu (nazwą naszego oznaczenia). Teraz, zeby znaleźć się w oznaczonej linii, w trybie komend wciskamy ‘X (najpierw apostrof, a później nazwę oznaczenia do którego chcemy przejść. A jeśli chcemy się przenieść dodkładnie do miejsca naszego oznaczenia (oznaczona kolumna) wprowadzamy `X (gdzie ` jest znakiem nad tyldą “~”, a X - nazwą oznaczenia).


Używam w moim .vimrc opcji zawijania długich linii (ale nie łamania ich). Przechodzenie w tym trybie między poszczególnymi liniami jest traktowane dosłownie: jeśli zawinięta linia zajmuje na ekranie 5 linii, przejście do następnej jest traktowane jako przejście za najbliższy znak końca linii (czyli wizualnie 5 linii). Przechodzenie między liniami tak jak w programach Windowsowych (czyli po jednej ‘wizualnej’ linii) rozwiązuje się poprzez wciśnięcie kolejno: gj (linia niżej) lub gk (linia wyżej). Aby kazać tak zachowywac się kursorom, możemy do naszego .vimrc wstawić:

nnoremap <Down> gj
nnoremap <Up> gk
vnoremap <Down> gj
vnoremap <Up> gk
inoremap <Down> <C-o>gj
inoremap <Up> <C-o>gk

Jak piszę nieco więcej kodu, lub przy refaktoryzacji/reformatowaniu tegoż, dość często szukam początku lub końca jakiegoś bloku. Najprościej jest wcisnąć kombinację klawiszy:

[{
żeby przenieść się na początek bloku
]}
na koniec bloku
[(
na początek nawiasu wewnątrz którego się znajdujemy
])
na jego koniec

Wklepywanie za każdym razem tych samych słów/tagów/poleceń jest męczące. Nawet dla tak zahartowanego ‘klepacza’ jak ja. Na szczęście, Vim potrafi pomóc w takich momentach.

Gdy chcesz wpisać jakieś słowo, które już występuje w tekście, zacznij je wpisywać, a nastęnie wciśnij <Ctrl+p> lub <Ctrl+n>. Pierwsza kombinacja wyszukuje wstecz, natomiast druga - do przodu, dany dokument, pod kątem występowania danego słowa. Następne wciśnięcia danego skrótu klawiaturowego spowoduje wyświetlenie kolejnego dopasowanego słowa. Np w tym tekście, powtarzają się dość często słowa ‘wpisać’, ‘wpisywać’ etc. Mogę sobie pomagać wklepując je, wpisując ‘wpi<Ctrl+p>’. W tym momencie Vim podpowiada mi wersje: ‘wpisać’, ‘wpisać’, ‘wpisywać’, i mogę sobie wstawić dowolną z nich (w wersji 7 wyświetla się okienko z listą dopasowanych słów, we wcześniejszych kolejno były dopasowywane słowa w danym miejscu).

Więcej na ten temat: :he complete


Strona 1 z 2