CGI programı örneği olarak zamanında yazıverdiğim program, programcılık açısından içler acısı:
/*
* Bu içeriği oluşturmak için bir kütüphane kullanmak çok daha yararlı
* olacaktır. Bunu küçük bir deneme olarak kabul edin:
*/
dout.writef("Content-type: text/html; charset=utf-8\n\n");
dout.writef("<html>\n <body>\n");
dout.writef(
`<b>Seçiminiz?</b><br>
<form method="GET" action="http://ddili.org/cgi-bin/deneme">
<input type="RADIO" name="hayvan" value="kedi"> Kedi<br>
<input type="RADIO" name="hayvan" value="köpek"> Köpek<br>
<input type="RADIO" checked name="hayvan" value="at"> At<br>
<br><b>Ne derece seviyorsunuz?</b><br><br>
<select name="derece" derece=1>
<option>Az
<option selected>Orta
<option>Çok
</select>
<br>
<input type="HIDDEN" name="sevilen hayvan" size="32">
<input type="Submit" value="Bir Düğme" name="birinci düğme">
<input type="Submit" value="Başka Düğme" name="ikinci düğme">
<input type="Submit" value="İptal" name="iptal">
</form>`);
dout.writef("\n<hr>\n<b>Ortam değişkenleri:</b><br><br>\n");
foreach (değişken; ortamDeğişkenleri) {
dout.writef("<b>%s</b>: %s<br>\n", değişken, getenv(değişken));
}
dout.writef("\n<hr><br>\n<a href=\"http://ddili.org/ornek_kod/deneme.d\">"
"(Bu çıktıyı oluşturan program)</a><br>\n");
dout.writef("\n </body>\n</html>\n");
:) O içerik tamamen elle oluşturuluyordu. Öyle bir içeriği program kodları ile oluşturmayı denedim. Sonuçta ortaya şöyle bir kullanım çıktı:
/*
* Bu içeriği oluşturan kütüphane geliştirilmeye devam ediyor. Bunu küçük
* bir deneme olarak kabul edin:
*/
auto içerik = sayfa();
içerik.ekle(
postFormu("http://localhost/cgi-bin/cgi_deneme",
bold("Seçiminiz?"), br(),
radyoDüğmeleri("hayvan",
[ Düğme("Kedi", "kedi"),
Düğme("Köpek", "köpek"),
Düğme("At", "at", SeçimDurumu.seçili) ],
br()),
br(), br(), bold("Ne derece seviyorsunuz?"), br(),
seçimListesi("derece",
[ Seçenek("Az"),
Seçenek("Orta", SeçimDurumu.seçili),
Seçenek("Çok") ]),
br(),
basılanDüğmeGrubu([ Düğme("Bir Düğme", "bir_düğme"),
Düğme("Başka Düğme", "başka_düğme"),
Düğme("İptal", "iptal") ])
));
içerik.ekle(çizgi(), bold("Standart giriş:"), br());
foreach (satır; stdin.byLine()) {
içerik.ekle(paragraf("satır: " ~ satır));
}
içerik.ekle(çizgi(), br(), bold("Ortam değişkenleri:"), br());
string[string] tanımlar;
foreach (değişken; ortamDeğişkenleri) {
tanımlar[değişken] = getenv(değişken);
}
içerik.ekle(tanımListesi(tanımlar));
içerik.ekle(çizgi(), br(),
bağlantı("(Bu çıktıyı oluşturan program)",
"http://ddili.org/ornek_kod/deneme.d"));
writeln(new HtmlBelgesi(içerik));
Bu haliyle önceki koddan daha uzun ama artık HTML içeriği ile oynamak çok kolay. Daha çoook değişikliğe ihtiyacı var. Şimdilik karalama olarak şöyle:
module xml_elemani;
import std.stdio;
import std.conv;
import std.string;
struct Nitelik
{
string etiket;
string değer;
this(const(char)[] etiket, const(char)[] değer = null)
{
this.etiket = etiket.idup;
if (değer) {
this.değer = değer.idup;
}
}
string toString() const
{
string sonuç = etiket;
if (değer) {
sonuç ~= format("=\"%s\"", değer);
}
return sonuç;
}
}
interface XmlElemanı
{
string girintili(int düzey) const;
}
class TekEleman : XmlElemanı
{
string etiket;
string değer;
Nitelik[] nitelikler;
XmlElemanı[] altElemanlar;
this(const(char)[] etiket, const(char)[] değer = null)
{
this.etiket = etiket.idup;
if (değer) {
this.değer = değer.idup;
}
}
TekEleman nitelik(const(char)[] isim, const(char)[] değer = null)
{
nitelikler ~= Nitelik(isim, değer);
return this;
}
TekEleman ekle(XmlElemanı[] altElemanlar ...)
{
this.altElemanlar ~= altElemanlar;
return this;
}
TekEleman ekle(ÇokluEleman çoklu)
{
TekEleman[] eklenecekler = çoklu.elemanlar;
if (eklenecekler.length) {
this.altElemanlar ~= eklenecekler[0];
eklenecekler = eklenecekler[1 .. $];
}
foreach (eklenecek; eklenecekler) {
if (çoklu.ayraç) {
this.altElemanlar ~= çoklu.ayraç;
}
this.altElemanlar ~= eklenecek;
}
return this;
}
string girintili(int düzey) const
{
enum girintiAdımı = " ";
string girinti = repeat(girintiAdımı, düzey);
string sonuç = girinti ~ '<' ~ etiket;
foreach (nitelik; nitelikler) {
sonuç ~= ' ' ~ to!string(nitelik);
}
if (altElemanlar.length || değer.length) {
sonuç ~= '>';
if (altElemanlar.length) {
foreach (eleman; altElemanlar) {
sonuç ~= '\n' ~ eleman.girintili(düzey + 1);
}
if (değer.length) {
sonuç ~= '\n' ~ girinti ~ girintiAdımı ~ değer;
}
sonuç ~= '\n' ~ girinti ~ "</" ~ etiket ~ '>';
} else {
assert(değer.length);
sonuç ~= değer ~ "</" ~ etiket ~ '>';
}
} else {
sonuç ~= "/>";
}
return sonuç;
}
override string toString() const
{
return girintili(0);
}
}
TekEleman sayfa()
{
return new TekEleman("body");
}
TekEleman bold(const(char)[] metin)
{
return new TekEleman("b", metin);
}
TekEleman br()
{
return new TekEleman("br");
}
TekEleman paragraf(const(char)[] metin)
{
return new TekEleman("p", metin);
}
TekEleman bağlantı(const(char)[] metin, const(char)[] bağ)
{
return (new TekEleman("a", metin)).nitelik("href", bağ);
}
TekEleman çizgi()
{
return new TekEleman("hr");
}
TekEleman radyoDüğmesi(const(char)[] seçenekMetni,
const(char)[] değişkenİsmi,
const(char)[] değer)
{
return
(new TekEleman("input", seçenekMetni))
.nitelik("type", "RADIO")
.nitelik("name", değişkenİsmi)
.nitelik("value", değer);
}
enum SeçimDurumu { seçili_değil, seçili }
struct Düğme
{
string metin;
string değer;
SeçimDurumu durum = SeçimDurumu.seçili_değil;
}
class ÇokluEleman : XmlElemanı
{
TekEleman[] elemanlar;
TekEleman ayraç;
this(TekEleman[] elemanlar, TekEleman ayraç = null)
{
this.elemanlar = elemanlar;
this.ayraç = ayraç;
}
override string girintili(int düzey) const
{
string sonuç;
const(TekEleman)[] yazdırılacaklar = elemanlar;
if (yazdırılacaklar.length) {
sonuç ~= yazdırılacaklar[0].girintili(düzey);
yazdırılacaklar = yazdırılacaklar[1..$];
}
foreach (eleman; yazdırılacaklar) {
if (ayraç) {
sonuç ~= '\n' ~ ayraç.girintili(düzey);
}
sonuç ~= '\n' ~ eleman.girintili(düzey);
}
return sonuç;
}
override string toString() const
{
return girintili(0);
}
}
ÇokluEleman radyoDüğmeleri(const(char)[] değişkenİsmi,
Düğme[] seçenekler,
TekEleman ayraç = null)
{
TekEleman[] grup;
foreach (seçenek; seçenekler) {
TekEleman eleman = radyoDüğmesi(seçenek.metin,
değişkenİsmi,
seçenek.değer);
if (seçenek.durum == SeçimDurumu.seçili) {
eleman.nitelik("checked");
}
grup ~= eleman;
}
return new ÇokluEleman(grup, ayraç);
}
struct Seçenek
{
string metin;
SeçimDurumu durum = SeçimDurumu.seçili_değil;
}
TekEleman seçimListesi(const(char)[] değişkenİsmi, Seçenek[] seçenekler)
{
TekEleman liste = (new TekEleman("select")).nitelik("name", değişkenİsmi);
foreach (seçenek; seçenekler) {
TekEleman eleman = new TekEleman("option", seçenek.metin);
if (seçenek.durum == SeçimDurumu.seçili) {
eleman.nitelik("selected");
}
liste.ekle(eleman);
}
return liste;
}
ÇokluEleman listeSatırları(string[] satırlar,
TekEleman ayraç = null)
{
TekEleman[] elemanlar;
foreach (satır; satırlar) {
elemanlar ~= new TekEleman(satır);
}
return new ÇokluEleman(elemanlar, ayraç);
}
TekEleman liste(const(char)[] listeÇeşidi,
const(char)[][] satırlar,
TekEleman ayraç = null)
{
TekEleman sonuç = new TekEleman(listeÇeşidi);
foreach (satır; satırlar) {
sonuç.ekle(new TekEleman("li", satır));
}
return sonuç;
}
TekEleman sıralıListe(const(char)[][] satırlar)
{
return liste("ol", satırlar);
}
TekEleman sırasızListe(const(char)[][] satırlar)
{
return liste("ul", satırlar);
}
TekEleman tanımListesi(const(char)[][const(char)[]] tanımlar)
{
TekEleman sonuç = new TekEleman("dl");
foreach (tanımAnahtar, tanımDeğer; tanımlar) {
sonuç.ekle(new TekEleman("dt", tanımAnahtar));
sonuç.ekle(new TekEleman("dd", tanımDeğer));
}
return sonuç;
}
ÇokluEleman basılanDüğmeGrubu(Düğme[] düğmeler, TekEleman ayraç = null)
{
TekEleman[] elemanlar;
foreach (düğme; düğmeler) {
elemanlar ~= (new TekEleman("input"))
.nitelik("type", "Submit")
.nitelik("value", düğme.metin)
.nitelik("name", düğme.değer);
}
return new ÇokluEleman(elemanlar, ayraç);
}
TekEleman form(const(char)[] yöntem,
const(char)[] eylem,
XmlElemanı[] elemanlar ...)
{
TekEleman form = (new TekEleman("form"))
.nitelik("method", yöntem)
.nitelik("action", eylem);
foreach (eleman; elemanlar) {
form.ekle(eleman);
}
return form;
}
TekEleman postFormu(const(char)[] eylem, XmlElemanı[] elemanlar ...)
{
return form("POST", eylem, elemanlar);
}
TekEleman getFormu(const(char)[] eylem, XmlElemanı[] elemanlar ...)
{
return form("GET", eylem, elemanlar);
}
class HtmlBelgesi
{
TekEleman belge;
this(XmlElemanı içerik)
{
belge = (new TekEleman("html")).ekle(içerik);
}
override string toString() const
{
return "Content-type: text/html; charset=utf-8\n\n" ~ to!string(belge);
}
}
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]