Emacs i formatowanie kodów źródłowych

Ten blog jest częściowo techniczny; blog anglojęzyczny jest techniczny praktycznie całkowicie. Często (częstawo?) potrzebuję wklejać w tekst (edytowany jedynie słusznym edytorem w jedynie słusznym języku znaczników) fragmenty kodu źródłowego. Jest parę rozwiązań, które mogę zastosować na blogaskach; oczywiście wszystkie kiepskie.

Można przeładować HTML-owy tag <pre>, za pomocą JavaScriptu albo pług-inów systemu blogowego. Drugie rozwiązanie może ma jakiś sens na Wordpressie, ale na Joggasku jest niemożliwe; JavaScript—fajnie, w większości przypadków działa, ale oskryptowywać się dla takiej pierdółki? HTML i CSS są całkowicie zdolne do pokazania ładnie sformatowanego i pokolorowanego kodu, bez uciekania się do pomocy skryptów. No i żaden skrypt w pehapie czy żawaskrypcie nie pokoloruje mi składni tak ładnie jak mój Emacs ;)

Emacs, z dodatkiem htmlize.el, potrafi zakodować bufor lub jego fragment do postaci pliku HTML, z zachowaniem kolorowania. Jeśli ustawimy zmienną htmlize-output-type na 'inline-css, to generowany jest HTML zdatny do przeklejenia prosto do pisanego kodu, ze stylami w formie <span style="…">. Dwa problemy: generowany jest cały HTML (z nagłówkiem itd), a kolor tła jest ustawiany w tagu body, a nie pre, co powoduje, że trzeba go przekleić. Zwykle robiłem to ręcznie, ale potrzebując przegenerować wszystkie przykłady potrzebne w drugiej części tutoriala Yaclml, wymiękłem.

Po pewnym czasie…

(require 'htmlize)

(defun jph/strip-htmlized-buffer ()
  "Strip htmlized buffer to <pre> tag, copying style attribute from <body> to <pre>."
  (interactive)
  (goto-char (point-min))
  (re-search-forward "<body\\( style=[^>]*\\)>")
  (let ((style (match-string 1)))
    (search-forward "<pre")
    (insert style)
    (delete-region (point-min) (line-beginning-position))

    (search-forward "</pre>")
    (delete-region (point) (point-max))
    (insert "\n")))

(defun jph/htmlize-fragment (prefix)
  "Replace fragment of current buffer with htmlized file.

Text between comments <!-- htmlize filename --> and
<!-- end htmlize --> gets replaced with htmlized file
`filename' (only the <pre> tag).

If a negative prefix is given, text between comments is removed.

Only one pair of comments is processed (nearest one forward from
current point position).
"
  (interactive "p")
  (when (search-forward "<!-- htmlize " nil t)
    (let ((source-file (thing-at-point 'filename)))
      (beginning-of-line 2)
      (let ((start (point)))
        (search-forward "<!-- end htmlize ")
        (beginning-of-line)
        (delete-region start (point)))
      (when (>= prefix 0) ; '-' prefix prevents inserting the htmlized text
        (insert (with-current-buffer (find-file-noselect source-file)
                  (with-current-buffer (htmlize-buffer)
                    (jph/strip-htmlized-buffer)
                    (prog1 (buffer-string)
                      (kill-buffer)))))))
    t))

(defun jph/htmlize-all-fragments (prefix)
  "Replace all indicated fragments of current buffer with htmlized files.

All pair of <!-- htmlize filename --> and <!-- end htmlize --> comments
are processed with `jph/htmlize-fragment'.  If negative prefix is given,
inside of all such comment pairs is deleted."
  (interactive "p")
  (goto-char (point-min))
  (while (jph/htmlize-fragment prefix)))

Powyższą wklejkę wpisałem w swój kod tak:

<!-- htmlize htmlize-fragments.el -->
<!-- end htmlize -->

Następnie wywołałem magiczne zaklęcie M-x jph/htmlize-all-fragments—i gotowe. Z ujemnym prefiksem (M-- M-x jph/htmlize-all-fragments) kod spomiędzy magicznych komentarzy jest kasowany (jeśli np. edytujemy tekst, a wielkie <pre> przetykane <span>-ami nas rozpraszają). Kod jest do przeklejenia stąd, albo do ściągnięcia pod adresem http://gist.github.com/285335. Smacznego!

Git, Squid, nagłówki…

Jakiś czas temu do zarządzania własnymi projektami przesiadłem się z darcsa na Gita. Nie jest aż tak intuicyjny, ale nie jest też aż tak zabugowany (w darcsie pewne rzeczy wydają się być broken by design) i ma o wiele większe możliwości. Nie narzuca użytkownikowi żadnego konkretnego modelu pracy, za to daje możliwość użycia w praktycznie dowolny sposób. Jednakowoż, TANSTAAFL. Jest o wiele trudniejszy w obsłudze i do sprawnego użycia wymaga jednak pewnej znajomości działania wnętrzności.

Ale tyle o słoniu. W końcu jakbym chciał na tym blogasku opisywać wszystko, co robię, to pisałbym chyba trochę częściej; porównań systemów kontroli wersji w sieci jest od groma i trochę, i nie ma potrzeby pisania jeszcze jednego. Ku pamięci swojej i innych chciałbym za to opisać, jak git zachowuje się w połączeniu z protokołem HTTP i serwerem pośredniczącym Squid po drodze, co zjadło mi spory kawał czasu dzisiaj, i nie jest tak trywialne. Otóż, w domu siedzę za wspomnianym Squidem – dostawca Internetu nie daje mi pod tym względem wyboru – a jedna z bibliotek, których używam i tworzę (konkretnie CL-Trane) jest dostępna jako repozytorium Gita po HTTP. Psuję ją sobie, psuję, na stanowisku roboczym pchnąłem poprawkę jakiegoś błędu, i próbuję ją pociągnąć na drugim komputerze… Already up-to-date. Łaty nie ma. Na serwerze – jest; po jakimś czasie nawet na repo.or.cz była widoczna; git clone na serwerze daleko-w-świecie widzi; na komputerze obok stacji roboczej, ani git pull, ani świeży git clone nie widzą. Ki czort?

Oczywiście, mógłbym przepchnąć tę konkretną łatę bezpośrednio z repo roboczego. Ale to niehonorowo, poza tym testowałem akurat instalację od zera (uwaga na boku: Capistrano rządzi rulezem), więc ręczne przeciąganie łatek popsułoby całą zabawę. Po poszukaniu trochę na temat transportu HTTP dla gita (który jest tzw. „głupim” transportem) dotarłem do magicznego pliku .git/info/refs; okazało się, że plik ten obejrzany przeglądarką tekstową na serwerze jest inny niż ten sam plik obejrzany z domu. Przeładowanie go z poziomu przeglądarki WWW doprowadziło zawartość do normy. Uff…

Okazuje się zatem, że Git jako klient HTTP grzecznie współpracuje z serwerami cache'ującymi i pośredniczącymi (co się chwali), ale gdy odpytuje, czy zawartość repozytorium dostępnego przez HTTP nie zmieniła się, jest aż za miły i wierzy serwerowi pośredniczącemu zamiast wymusić na nim sprawdzenie tego bezpośrednio u źródła. Trzeba to na serwerze wymusić samemu, korzystając z przeglądarki, wget --no-cache, czy nawet (opcja dla geeków-superbohaterów) bezpośrednio telnetem lub netcatem. Dobrej zabawy! ;)

Wikibabel - słownik z Wikipedii

Nie wiem, jak szanowni Czytelnicy, ale ja czasem korzystam z Wikipedii jako słownika. Posiada ona bowiem, w lewym panelu, sekcję „w innych językach,” a baza wyrazów Wikipedii (przynajmniej dla tych języków, w których zdarza mi się czegoś szukać) jest o niebo większa niż większości słowników dostępnych online. Co więcej, Wikipedia wspaniale się sprawdza przy tłumaczeniu nazw roślin, przypraw itp, do czego nie nadają się jednojęzyczne słowniki papierowe — to, że daffodil to jest nazwa kwiatu, jestem w stanie zrozumieć z kontekstu, za to przydałoby się wiedzieć, jaki to konkretnie rodzaj badyla… a że biologiem nie jestem, zamiast opisu wolę jednak nazwę w moim języku.

Kilka dni temu odkryłem, że MediaWiki (silnik Wikipedii) udostępnia publicznie API. Wieczór z PHP, dwa kolejne z CSS, lo and behold: WikiBabel.

Przy okazji wyłonił się zabawny ficzer tłumaczeń Wikipedyjnych: dla wyrazów bliskoznacznych (np. gałka muszkatołowa / muszkatołowiec) i homonimów (np. „kuchnia”) linki do stron w innych językach często są jednokierunkowe. Nie wspomnę już o zamieszaniu robionym przez strony ujednoznaczniające. Zastanawiam się, czy da się to jakoś obejść/poprawić…

Na razie mam nadzieję, że wyskrobany przeze mnie kawałek kodu komuś się przyda. Smacznego!

GSoC Status Update, week 12½ (final)

Seriously, where did this half a week come from? I can understand periods of time disappearing, but half a week appearing out of nowhere is something new to me. But I won't complain – extra time is good. ;)

Pencils down now. Of course, project continues, but evaluations for Google will be based on what is done now, thus gsoc_2008_pencils_down tag in darcs. The second tag is much nicer, it's 1_0_rc1. I think I got to a passable 1.0 version now. It may need some more unit tests (as always), documentation polishing, most probably there may still be bugs, and I don't want to call it a full 1.0 version before using the library in some actual application. Besides that, feature-, documentation- and API-wise all seems to be complete.

Work done since last report

  • Fixed some bugs, esp. portability to other Lisps
  • Some polishing (dropping unnecessary format string/argument pairs, renaming accessors, dependency updates, things like this)
  • Documentation!
  • Some unit tests (not that much)

Problems

This “Problems” section will list what doesn't seem to be complete after the “pencils down” timestamp rather than current problems. Completing those will go into 1.1:

  • Unit tests don't cover much of actual protocol code. Not sure exactly how to do this, and whether it's worth to do it. We'll see.
  • YADIS (#7), and Relying Party discovery (#13). Yadis support should be moved to a separate library, and used for discovering Relying Party return_to endpoints.
  • Random number generation (#14). The rfc1750 should be implemented as a separate library atop Ironclad for secure pseudo-random number generation. Currently plain CL:RANDOM is used, which is not acceptable for security-sensitive deployments.
  • With regard to original proposal, most of portability has been deemed actually irrelevant. Web server portability has been achieved, web client and storage portability has been dropped. All storage is in-memory and that's enough (keeping user data is responsibility of library's user, and associations / nonces/ authentication processes can be kept in memory).
  • API for 1.0 was deliberately kept as simple and small as possible to have any functioning relying party or provider. Intended side-effect is that it may not be flexible enough to support users' actual needs. I decided to keep API small and simple, and to extend it to actual users' requirements, instead of trying to get most comprehensive API ever. Not actually a problem, but connected with above (when need for HTTP client or storage portability will actually arise, it will be added).
  • Relying Party and Provider are not separate systems; the specific RP/OP code is small, and the required libraries are common anyway. It will most probably stay this way.
  • Logging. As for now, logging is responsibility of CL-OpenID user. Maybe it would be useful if library itself was able to log events. Not before 1.1, though.

Plans for future

Similarly to problems, final report's plans are also referring to the general future instead of next half-week. I intend to support the library, and use it in my own Web projects. Current state of code is labeled 1.0rc1; after some discussions with users, using CL-OpenID in own code, I will label it 1.0. It will need to wait a bit, as bugs and omissions will surely manifest. I expect to have final 1.0 in September. After that, issues listed in “Problems” section are more of a TODO list for 1.1. When that is done, some actual deployments will be already done, and I will be able to tell whether it's maintenance phase already, or should the development continue to 1.2 or 2.0.

So, that's it. Pencils down. Planet PLD and other planet spammage by these reports will cease (contrary to some comments, there seems to be no spammage anywhere else since about two weeks, when I stopped redirecting those posts to techblog; if I'm wrong, please correct me even if it's too late). Now, off to announce 1.0rc1 to the world!

GSoC Status Update, week 12

Final weekend ahead. Finishing the code, writing tests, docs, ensuring consistency… 1.0 is definitely on the radars.

Work done since last report

  • Discussed bugs, priorities and requirements for 1.0
  • Fixed bugs (#9, #12, few unlisted ones)
  • Added comments to example code, polished comments
  • Added some exports (message API and AUTH-PROCESS accessors)
  • Add a bunch of tests, especially for message API
  • Started working on documentation (locally, not commited yet)

Problems

None

Plans for next half week

  • Add thread-safety and dependency on bordeaux-threads
  • Finish documentation
  • More tests, as many as possible

Since Monday 19:00 UTC is Google's pencils down date, next report (and last one of this form) will be sent on Monday evening instead of usual Tuesday.

GSoC Status Update, week 11½

Final week ahead. Time to focus on documentation and polishing; some bugs still left, mostly nontrivial ones, and not everything is covered by unit tests, but core functionality and final (I think) API is in place.

Work done since last report

  • Moved code to proper source files, finalized source layout (I think)
  • Separated examples
  • First-class RP and OP, finalize proposed API
  • Some minor tweaks and doc/comment updates
  • Exported basic proposed API
  • Fixed most of remaining bugs

Problems

Some bugs still left. Mostly they are nontrivial and I am a bit afraid to destabilize the code in last days before the deadline. Relying party discovery will have to wait until after the deadline. However, I think at least some of them should be fixed; however, I will focus more on documentation and tests.

Plans for next half week

  • Discuss API
  • Documentation: finish docstrings, start a DOCUMENTATION-TEMPLATE-based doc
  • If time permits, comment examples
  • Add tests
  • Fix some outstanding bugs and suggestions: thread-safety, maybe realm checking

GSoC Status Update, week 11

Refactoring is approaching end. I hope to have it done on the weekend, and spend final week on documentation and examples.

Work done since last report

  • Updated internal message API to take care of formatting URIs, integers, and octet vectors as strings
  • Use message API throughout the code
  • Minor comment/documentation updates

Problems

None.

Plans for next half week

Finish refactoring:

  • First class OP and RP
  • Separate example code
  • Fix outstanding bugs from Trac
  • Export symbols for final API

GSoC Status Update, week 10½

Work done since last report

  • Add message utility functions and rewrite part of code to use those instead of list-level mangling
  • Many minor bugfixes and cosmetic (formatting, naming consistency etc) fixes
  • Comment and docstring fixes
  • Fix possible DoS: Use counters instead of GENTEMP for generating unique IDs, don't inter endpoint URIs when associating
  • Introduce and use AUTH-PROCESS structure instead of ID alist
  • Update tests, add some for newly introduced functions

Problems

None.

Plans for next half week

  • Write more tests
  • More docstring fixes
  • Introduce first-class RP and OP, if time permits
  • Logging, if time permits

GSoC Status Update, week 10

Work done since last report

  • Discussed refactoring and final API, reaching conclusion on most issues
  • A bit of general cleanup
  • Docstring and comment additions
  • More moving to shared.lisp
  • Moved message-specific functions to message.lisp

Problems

Work actually done differs a bit from what I was planning to do mainly as a result of the discussion mentioned in previous section. The message class idea has been rejected since it was really a premature optimization (which, as we all know, is root of all evil) – so I backed out of it, and stayed with alists, but separated message-related code.

Plans for next half week

  • Finish factoring out messages
  • Tests!
  • Authorization process structure (for what is called ID across the code)

GSoC Status Update, week 9½

Work done since last report

  • Improved OpenID v1 compatibility in provider
  • Moved general library functions to shared.lisp
  • Few one-line fixes, cosmetics, docstrings, formatting etc
  • (uncommited) Started work on MESSAGE structure, which will represent a single OpenID protocol message and will be one of base types after refactoring.

Problems

None whatsoever.

Plans for next half week

  • Tests for shared.lisp functions
  • Review existing tests, update or temporarily comment out outdated ones
  • Finish MESSAGE structure and use it thorough prototypes
  • Tests for MESSAGE class, if time permits

Kategorie

Archiwum