Z jakiś powodów obsługi przez Perla UTFa nie może być bezszmerowa. Zawsze coś nie działa i zawsze jest problem. I zawsze jest kombinowanie co by tu wstawić za zaklęcia żeby działało. Np. to zwykle działa:
#!/usb/bin/perl use locale; use utf8; binmode(STDOUT, ":utf8"); ##use open ":encoding(utf8)"; use open IN => ":encoding(utf8)", OUT => ":utf8";
albo to poniżej też czasami działa (wtedy kiedy powyższe nie działa):
use utf8; binmode(STDOUT, ":utf8"); use open ":encoding(utf8)";
Czasami nawet nie potrzeba ostatniego
use open ":encoding(utf8)";
. Czemu nie wiem. Nadmiarowe
polecenia psują kodowanie BTW (jakby ktoś myślał, że jak wstawi wszystkie
polecenia, które dotyczą kodowania UTF ,,na zapas'' to będzie zawsze dobrze.)
Od ręki nie działa. Próbowałem rozwiązać problem instalując następujące pakiety:
yum install gphoto2 gvfs-gphoto2 gtkam digikam gthumb geeqie
Geeqie
to zamiennik gqview
,
które używałem do tej pory.
DigiKam
nie działa (gryzie się z XFce
).
Wydaje mi się, że większość tego
co zainstalowałem
nie jest potrzebna -- istotne jest geeqie
,
dzięki któremu mogę wygodnie
zaimportować zdjęcia
z aparatu na komputer (lądują w katalogu ~/Pictures
).
Prawie działa. Problem stanowią słowa kluczowe zawierające
polskie znaczki. Trzeba nieco zmodyfikować skrypty generujące
bazę słów kluczowych tj. flickr_getalltags
, i inne.
Cała procedura odświeżania tagów i innych metadanych jest
uruchamiana skryptem flickr_update_kb
, który
w uproszczeniu wygląda następująco:
#!/bin/bash # Get list of public photos with 'flickr.people.getPublicPhotos flickr_getphotolist.pl -u hr.icio # Refreshing information on tags/sets/geolocs" # Get information on sets defined by the user: flickr_getsets && \ # Get tags from flickr for current user flickr_getalltags && \ # Get information on groups to which one can add photos flickr_getgroups && \ ## For flickr_xml2el we need _special treatment_ otherwise UTF is spoiled PERL_UNICODE=S flickr_xml2el > ~/.flickr/hr.icio.el cd ~/.knows && make 2flicker && \ cd ~/.flickr && make check
Z nieustalonych powodów cześć komunikatu zwracana przez flickra
jest teraz kompresowana (a nie była -- nowsza wersja pakietu Perla?).
Z tego też powodu konstrukcja (ze
skryptu flickr_getalltags.pl
-- w innych skryptach
podobnie):
my $xm = $xmlp->XMLin($response->{_content}, forcearray=>[raw]);
została zamieniona na:
## zmienione 15.08.2011 (gzip as content-encoding) ## ustalenie w jakim `content_encoding' jest _content my $content_encoding = $response->{_headers}->{'content-encoding'} ; my $plain_content; if ($content_encoding =~ /gzip/ ) {## jeżeli gzip to odpakować: $plain_content = Compress::Zlib::memGunzip( $response->{_content}); } else { $plain_content = $response->{_content}; }
Powyższe załatwia problem z (nie) działaniem skryptów
flickr_getphotolist.pl
,
flickr_getsets
,
flickr_getalltags
,
flickr_getgroups
.
Konwersja plików XML do formatu Emacsa
za pomocą skryptu flickr_xml2el
daje w rezultacie las
komunikatów Wide character in print at... a plik wynikowy jest
błędnie kodowany. Problem ciągle wraca a ja ciągle nie wiem czemu.
Zaślepkowo pomogło
dodanie PERL_UNICODE=S
(zaklęcie to należy wstawić
w odpowiednie miejsce
także do pliku Make
w katalogu ~/.knows
).
Po tych wszystkich ww. zabiegach (które zajęły mi pół dnia) jestem w stanie odświeżyć bazę metadanych z mojego konta na flickr.com. Sukces:-)
Dawno temu zrobiłem systemik formatujący pewien plik XML do postaci pliku PDF. Ten cel jest realizowany na dwa pas. Najpierw skrypt Perla zamienia XML na plik TeXa, który to plik jest zamieniany pdfTeXem na dokument PDF. 10 lat działało i nagle ktoś dostrzegł, że zakładki (bookmarks) są nie po polsku. No nie są, bo kiedyś było to trudne do wykonania... A teraz faktycznie nie jest trudne -- wystarczy zamienić kodowanie z jednobajtowego na UTF-8.
Po tej właśnie linii zaatakowałem problem, tj. 1) zmieniłem kodowanie w generowanym pliku TeXowym z ISO8859-2 na UTF-8 oraz, w związku z tym 2) zmieniłem pdfTeXa na XeTeXa. Jak zwykle nie obyło się bez problemów:
Elementy nawigacyjne są definiowane inaczej w XeTeXu niż w pdfTeXu, więc za pierwszym razem bookmarki zniknęły w ogóle. Gdybym swoje makra pisał w LaTeXu problem by nie istniał, ale w plain TeXu zwykle trzeba wszystko samemu... Tym razem na szczęście z pomocą google znalazłem działające gotowe makra pn. navigator.
Kolory też są inaczej definiowane. Ja to zrobiłem tak:
\def\cmykRed{0 1 1 0} \def\setcolor#1{\special{color push cmyk #1}} \def\endcolor{\special{color pop}} \setcolor\cmykRed \bf Cośtam-coś-tam-na-czerwono \endcolor
Miłą cechą XeTeXa jest to, że można korzystać z fontów systemowych. Wymyśliłem zatem, że dokument będzie składany fontem TeX Gyre Heros w odmianie wąskiej. Można to zadeklarować następująco:
%% Podstawowym fontem jest TeX Gyre Heros w odmianie `Condensed' %% cf. http://www.gust.org.pl/projects/e-foundry/tex-gyre/heros \def\MainFont{TeX Gyre Heros Cn}\def\MainXFont{TeX Gyre Heros} \font\rm = "\MainFont:mapping=tex-text" \font\bf = "\MainFont/B:mapping=tex-text" \font\it = "\MainFont/I:mapping=tex-text" %% W stopniu 8pt zamiast odmiany wąskiej używamy normalnej %% \font\eightrm = "\MainXFont:mapping=tex-text" at 6.25pt \font\eightbf = "\MainXFont/B:mapping=tex-text" at 6.25pt \font\eightit = "\MainXFont/I:mapping=tex-text" at 6.25pt
Zapis mapping=tex-text
oznacza, że font ,,reaguje'' na TeXowe ligatury, m.in
--
oraz ---
zamieniając je (odpowiednio) na półpauzę i pauzę.
Zapis /B
włącza odmianę grubą a /I
kursywę...
I gdy już wszystko było prawie gotowe nieopatrzenie zajrzałem do pliku .log
a tam cała masa wpisów:
Invalid UTF-8 byte or sequence at line 22 replaced by U+FFFD.
Czyli Perl jednak sygnalizował coś brzydkiego wypisując:
Wide character in print at ....
Mój skrypt czyta plik XML, parsuje go z wykorzystaniem XML::Parser
,
który to -- jak powszechnie wiadomo -- wypluwa dokument w UTF-8.
Więc czemu w efekcie dostaję błędnie kodowany plik??
Ustalenie co
jest nie tak zajęło mi kilka godzin a sprawa sprowadzała się do dodania:
open (OUT, ">:utf8", "plik-out") # zamiast open (OUT, ">plik-out")
zamiast open (OUT, ">:utf8"...
można wpisać:
use open ":encoding(utf8)"; use open IN => ":encoding(utf8)", OUT => ":utf8";
Wpisanie zaś:
use utf8 ;
wskazuje tylko tyle, że skrypt Perla jest kodowany w UTF-8.
Do wpisywania literalnych fragmentów tekstu używam otoczenia
Verbatim
z pakietu fancyvrb
. Otoczenie to m.in. może
być wstawione do przypisu oraz jest możliwość umieszczania
w tekście literalnym poleceń formatujących. To drugie przydaje się przykładowo w sytuacji
gdy w opisie składni jakiegoś języka pewne fragmenty są meta, tj. nie należy
przepisywać ich literalnie ale oznaczają pewne pojęcia (jak dajmy na to
element replaceable
wewnątrz
literallayout
w Docbook), przykładowo:
\begin{list}{punktor}{deklaracje} zestawienie \end{list}
Można wpisać:
\begin{Verbatim}[commandchars=@\{\}] \begin{list}{@emph{punktor}}{@emph{deklaracje}} @emph{zestawienie} \end{list}
Jeżeli fragmenty literalne mają być mniejsze
to można dopisać po przecinku fontsize=\small
. Inną potencjalnie
przydatną opcją jest numerowanie wierszy:
\begin{Verbatim}[commandchars=@{},fontsize=\small,numbers=left] \begin{list}{@emph{punktor}}{@emph{deklaracje}} @emph{zestawienie} \end{list}
Numery nie muszą się zaczynać od 1. Opcja firstnumber
pozwala
na kontynuację. Można w szczególności wpisać firstnumber=last
i numerowanie rozpocznie się od wartości o 1 większej niż ostatni wiersz
w poprzednim otoczeniu Verbatim
.
Można też wykorzystując polecenie \fvset
zdefiniować
powtarzające się opcje globalnie a nie wpisywać je za każdym razem:
\usepackage{fancyvrb} \VerbatimFootnotes % <-- verbatim można umieszczać w przypisie \DefineShortVerb{\"} % <-- krótka forma zapisu "foo" zamiast \verb@foo@ \fvset{commandchars=¤´˝} \makeatactive \newenvironment{literalexample}{\begingroup \endgraf \small \medskip \Verbatim}% {\endVerbatim \par \medskip \endgroup \@doendpe } \makeatother \begin{document} \begin{literalexample} \@startsection{¤emph´nazwa˝}{¤emph´poziom˝}{¤emph´wcięcie˝}{¤emph´odstęp-przed˝}{¤emph´odstęp-po˝}{¤emph´styl˝} \end{literalexample}
W powyższym przykładzie \@doendpe
powoduje, że
w pierwszym akapicie po otoczeniu literalexample
nie będzie wcięcia.
\Verbatim
i \endVerbatim
,
to otoczenie Verbatim
zapisane w postaci pary poleceń (każde otoczenie LaTeXa można
zapisać jako
\Otoczenie
i \endOtoczenie
.
Ponieważ w kodzie LaTeXa praktycznie występują wszystkie znaki z klawiatury
jako commandchars zastosowałem znaczki z górnej połówki ASCII:
¤
(dziesiętnie 164) ´
(180) oraz ˝
(189).
Można by stosować np. ¤{}
, ale wolałem nie używać {}
w roli ograniczników do ¤
, żeby mi się nie mieszało z nawiasami
klamrowymi wstawionymi literalnie.
Teraz większy przykład, jak to działa
%& --translate-file=il2-pl \documentclass[a4page]{book} \usepackage{fancyvrb} \fvset{commandchars=¤´˝} \usepackage{polski} \begin{document} \begin{Verbatim} \begin{list}{¤emph´punktor˝}{¤emph´deklaracje˝} ¤emph´zestawienie˝ \end{list} \end{Verbatim} \end{document}
Znaczki ¤´
oraz ˝
wstawiam w Emacsie wciskając
C-c [
oraz C-c ]
.
W tym celu w .emacs
zdefiniowałem co następuje:
(defun insert-commandchars-open () "Insert sequence of characters character 164-180" (interactive) (insert "¤emph´") ) (defun insert-commandchars-close () "Insert sequence of characters character 189" (interactive) (insert "˝") ) (global-set-key "\C-c\C-[" 'insert-commandchars-open) (global-set-key "\C-c\C-]" 'insert-commandchars-close)
Teraz jeżeli byśmy na-rympał chcieli to używać z opcją utf-8
albo latin2
pakietu inputenc
, to no-way:
\documentclass[a4page]{book} \usepackage[utf8]{inputenc} \usepackage{lmodern} \usepackage[T1]{fontenc} \usepackage{fancyvrb} \fvset{commandchars=¤´˝} \usepackage{polski} \begin{document} \begin{Verbatim} \begin{list}{¤emph´punktor˝}{¤emph´deklaracje˝} ¤emph´zestawienie˝ \end{list} \end{Verbatim} \end{document}
LaTeX zgłasza błąd:
! Package inputenc Error: Keyboard character used is undefined
BTW: zapewne \fvset{commandchars=@\{\}}
zadziała, ale nie
chce mi się sprawdzać...
Można spróbować też XeTeXa:
\documentclass[a4page]{book} \usepackage{fontspec} %<-- włącza LM wymaga xetexa \usepackage{fancyvrb} \fvset{commandchars=¤´˝} \usepackage{polski} \begin{document} \begin{Verbatim} \begin{list}{¤emph´punktor˝}{¤emph´deklaracje˝} ¤emph´zestawienie˝ \end{list} \end{Verbatim} \end{document}
Działa...
W nazwiązaniu do poprzedniego wpisu. W dokumencie o XPath pojawia się taki oto fragment:
[predykat]*]]>
Co ma oznaczać, że wyrażenie ścieżkowe XPath składa się z osi
i testu oraz opcjonalnego predykatu, który może być powtórzony
wielokrotnie (stąd *
).
Teraz standardowo szablony
XSL Docbook (aka XSLDB) zamieniają ww. fragment XML na coś takiego:
oś::test[[predykat]*]
Niezręczność polega na tym, że nawiasy kwadratowe raz są używane do
oznaczania części opcjonalnej a raz oznaczają, że należy je wstawić
literalnie. W XSLDB znaki wstawiane wokół
elementu optional
są sparametryzowane -- są to mianowicie:
arg.choice.opt.open.str
oraz
arg.choice.opt.close.str
.
Zamiast `[' i `]' zdecydowałem
się na U+27E8
(Mathematical left angle bracket) oraz U+27E9
(Mathematical right angle bracket) Teraz próba uruchomienia:
xsltproc --stringparam arg.choice.opt.open.str "⟨" \ --stringparam arg.choice.opt.close.str" select="⟩" ...
Kończy się błędem basha... Ciekawe czemu? Można podać ww. znaki binarnie -- wtedy wszystko działa. Ale UTF-8 w Makefile? Miałem opory, dodałem więc do arkusza uruchamiającego transformację XML → XHTML:
<xsl:param name="arg.choice.opt.open.str" select="'⟨'" /> <xsl:param name="arg.choice.opt.close.str" select="'⟩'" />
Teraz omawiany fragment wygląda mniej dwuznacznie:
oś::test⟨[predykat]*⟩
BTW w trybie nxml wpisanie ⟨
powoduje, że automagicznie
kształt znaku pojawia się za średnikiem (ale nie jest wstawiany do tekstu --
po prostu jest to podpowiedź Emacsa, jak wygląda kształt znaku.)
Dodatkowo po
najechaniu myszą na encję wyświetlana jest nazwa znaku (w oknie podpowiedzi zwanym tooltip).
Te ułatwienia są fajne w środowisku jednobajtowym--a ja póki co
używam jako domyślnego kodowania ISO-8859-2.
Przy okazji użyteczne zestawienie
znaków Unicode -- odpowiedników różnych TeXowych symboli matematycznych. Wystarczy zaznaczyć myszą
i wkleić do Emacsa a następnie C-x =
(what-cursor-position
)
wyświetli co zacz, w tym numer znaku.
Emacs 22 działa z UTF-8 out-of-the-box. Miałem dziwny problem, cały bufor zmienił się w drobną kaszkę (co widać obok--musiałem go odtworzyć via Google btw). Podejrzewałem moją funkcję do wstawiania niełamliwej spacji.
(defun insert-nbspace() "Insert character 160, no-break space " (interactive) (insert " ") )
Okazało się jednak, że ww. funkcja nie powoduje problemów a teraz nawet nie mogę odtworzyć błędu, który wtedy wystąpił. Tak czy owak, pliki UTF-8 są otwierane jako UTF-8, a te kodowane jednobajtowo jako ISO-8859-2. W Gnus 5.11 też to wszystko działa, do tego smilies sa w full kolorze. Rewelacja. Tim Bray (ten od XML) też używa Emacsa.