Ev Arşiv Hakkında

Vim için Clojure çalışma ortamı(vimclojure + SLIMV)

1-7-2011, 5:19 ö.s. // yorum // vim , lisp

Islah olmaz bir Vim kullanıcısı olduğumdan(yine de Vim ile Java yazmayı denemiyorum, heh), her işimi Vim ile görmeye çalışıyorum. Şu ana kadar kullandığım diller arasında, Java'yı saymazsak, beni en çok uğraştıran Clojure oldu.

Genel olarak 2 yol var. Birincisi, Emacs'in SLIME klonu olan SLIMV. Common Lisp, Scheme ve Clojure için kullanılabiliyor. Fakat Clojure desteğinde bazı sorunlar var. İkincisi, vimclojure. Clojure düzenleme yetenekler SLIMV'e göre çok daha iyi, ama REPL kısmı biraz sıkıntılı. Lein REPL kullanamıyorsunuz, Nailgun kullanıyor. Yavaş çalışıyor. Göçtüğünde bir daha başlatması, bir işlemde takıldığında durdurması vb. şeyler zor.

Benim izlediğim yol, SLIMV üzerine vimclojure syntax renklendirme ve indentation scriptlerini kullanmak oldu. Normalde SLIMV'in Clojure indentation kısmında birkaç problemi var. Clojure keyword'lerini de tanıymıyor.

Bunu yapmanın en kolay yolu, benim vim ayar dosyalarımı çekip(github) veya ayar dosyalarımdan /bundles/slimv/i çekip gerekli yerlere atmak. Onun dışında, bir hata durumunda bana sövmeyin diye ne yaptığımı da açıklayayım. Standart SLIMV(0.8.4 kullandım, 0.8.5 REPL ekranı daha yavaş çalıştı nedense, yazarı olmaması gerektiğini söyledi ama, bir daha kurcalayacağım bir ara) altına, autoload klasörü oluşturup vimclojure autoload scriptini kopyaladım. Bu bana vimclojure fonksiyonlarını sağladı(syntax renklendirme ve indentation için gerekecek). Daha sonra slimv/indent/clojure.vim ve slimv/syntax/clojure/slimv-syntax-clojure.vim dosyalarının içeriğini vimclojure scriptlerininkiyle değiştirdim. Bu kadar.

SLIMV'in eksikleri var. Geliştiricisiyle stackoverflow'da karşılaştım ve şu anda birkaç eksikliği düzeltmek için uğraşıyor. Birincisi, lein repl kullanmasına rağmen, javadoc source gibi bazı fonksiyonları (use '[clojure.repl :only (source apropos dir pst doc find-doc)]) ile kullanmanız gerekiyor. Normalde terminalden lein repl ile çalıştırırsanız bunları direkt kullanabiliyorsunuz ama. İkincisi, program bir noktada takılırsa(uzun bir işlem vs) durdurmanın bir yolu yok(ya da ben bulamadım).

Aslında SLIMV varken sıfırdan bir Clojure scripti yazmak çok saçma geldi bana. Vimclojure yazılacağına SLIMV Clojure desteği üzerinde uğraşılsaymış çok daha güzel birşey olacakmış. Şimdi ben kendim ikisinin güzel özelliklerini kullanmaya çalışıyorum mesela.

GUI programlama, IDEler, ve Python hakkında

22-5-2011, 1:08 ö.s. // yorum // python , java , ödev , vim , lisp

Son birkaç gündür yoğun bir şekilde GUI programlama ve Java ile uğraştım. İlk başta 2 arkadaşımla beraber basit bir chat sunucu/istemcisi yazmaya başladık(kaynak koda github depomuzdan erişebilirsiniz). Daha önceki tecrübelerimden (lisede web tasarım, daha sonra Python + GTK/QT ile arayüz denemelerim) arayüz tasarımından ne kadar nefret ettiğimi bildiğimden, bu projede ben sunucu ve istemci altyapısını hazırlamakla uğraştım. Fakat sonra bir ödev gereği, arayüz tasarımıyla da kendim uğraşmam gerekti.

Ödev Java ile yapılacaktı ve dolayıyısla arayüz olarak Swing kullandım. Başlangıç için Eclipse için WindowBuilder eklentisi ile ana çerçeve + layoutları oluşturup daha sonra elle yazdım. Bu süreçte şunu farkettim, adam gibi bir IDE, işleri daha önce tahmin edemeyeceğim kadar kolaylaştırıyor. Asıl olarak Python ile yazan biri olarak, birkaç gün öncesine kadar her işimde VIM kullanıyordum ve çok da memnundum(arayüz tasarımı yapmıyorum). Şu birkaç gün(sadece ödev için 1460 satır kod) bazı şeyleri farketmemi sağladı.

Onlarca sınıf, her sınıf için onlarca method, ve bu sınıflar arasında karışık ilişkilerin olduğu bir işle uğraşıyorsanız, iyi bir IDE şart. Dökümantasyonda geçirdiğiniz çok kısaltıyor.

Static typing çok hoş bir olay. Okula başladıktan sonra bol miktarda C(programlama yarışması) ve Java(ödevler) uğraşmam gerekti. Henüz sadece birkaç dili birşeyler üretebilecek seviyede biliyorum ve bu konuda çok da bilgili değilim, ama Python ile en çok dökümantasyon ve IDE sıkıntısı çekiyorum. Ücretli IDEleri denemedim ama denediğim tüm ücretsiz Python IDEleri Autocomplete konusunda çaresiz kalıyorlar. Python'da aşağıdaki gibi birşey görebilmek için herşeyimi(?!) verirdim:

Hatta mesela şöyle birşey yapabilseydim:

Ama yok, örneğin PyDev daha aşağıdaki kodda çakılıyor:

cls = Class1()
cls.

Daha burda bile, Class1'in methodlarını gösteremiyor. Direkt olarak Class1. şeklinde yazıp, autocomplete çalıştırırsak, methodları gösteriyor, bu iyi, fakat bu sefer de bound-unbound method farkını anlayamıyor ve bound methodları da gösteriyor. Ki bound methodlar bu şekilde çağırılamaz. Fail.

WingIDE diyenler için, personal sürümü, sanki "öyle gerekli özellikler çıkaralım ki, kimse almasın" diye düşünülerek hazırlanmış. O kısıtlı özellikleri çıkardığımızda, Vim ile de yapıyorum zaten geri kalanları. Burdan bakın. Professional sürümü de çok pahalı.

PyCharm diyenler için, Open Source lisansı ücretsiz, fakat Open Source Definition'a uyan bir projeniz olmalı. Benim yok.

Eclipse, Java'nın verdiği acıyı inanılmaz derecede hafifletiyor. Yoksa sınıflar arasındaki saçma derecede karmaşık ilişkiler başka türlü çözülemez. Python'da ise, benzer karışıklıkta tasarlanmış(muhtemelen başka bir dilde, örneğin QT için C++) bir kütüphane ile çalışıyorsanız, acınızı hafifletecek hiçbir şey yok.

Konudan biraz sapacağım ama, Python hakkında beni sinirlendiren bir başka konu da, threading ve socket olayları. Ne zaman socket veya threading kullansam, mutlaka bir problemle karşılaşıyorum ve bunu ne zaman IRC'de sorsam, mutlaka birileri Twisted kullanmamı söylüyor. Kötü alışkanlıklardan, yanlış programlamadan vs bahsedip duruyorlar. Sanki Freenode #python kanalında, içinde şöyle bir kod olan bir sürü bot varmış gibi:

if "socket" in msg or "thread" in msg:
    self.reply(msg, "Use twisted!!1 bad habits good code debugging bla bla bla")

Java'da yaklaşık bir hafta kadar önce kullanılabilr bir hale getirdiğimiz chat istemci/sunucusu, dilin kendi thread ve socketlerini kullanıyor. Thread ve socket kullanımı ile alakalı dökümantasyon hariç hiçbir yere baktığımı hatırlamıyorum. Python'dan gelen birisi olarak şaşırtıcı derecede kolay ve stabil oldu.


Bir süredir kafamda kendi IRC istemcimi yazma fikri var. Şu anda yazabilmek için gerekli herşeyi biliyorum. Dün oturdum, Java ve Python'da IRC sunucusuna bağlanabilmek için gerekli en küçük kodu yazmaya karar verdim(arayüz ile beraber). Java'da, kendi socket ve thread sınıfları ve Swing ile kolayca yazdım(bu arada Swing'in ne kadar kötü gözüktüğüne dikkat, platform bağımsız olarak iğrenç gözüken bir arayüz kütüphanesi kendisi, ehehe):

Python'da QT kullandım. Fakat garip bir şekilde, ne zaman sunucudan bir mesaj gelse, QT segmentation fault veriyor:

QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
Segmentation fault

IRC'de sorduğumda aldığım yanıtı tahmin edersiniz zaten.

Şimdi oturup düşünüyorum, bir yanda Java, sadece dilin kütüphaneleri ile sunucuya bağlanıp, mesaj gönderip aldığım kod, arayüz ile beraber hazır bile. Elimin altında Eclipse gibi bir IDE var. Python ile yapmak istersem, ekstra olarak uğraşmam gerekecek şeyler: PyQT'nin dökümantasyonu, Twisted'ın dökümantasyonu, Twisted'ı öğrenmek, QT Designer ile tasarımı koda çevirmek için ekstra bir işlem yapmak, daha sonra bir daha QT Designer ile değişiklik yapamamak(Eclipse + WindowBuilder ile tasarım/kod arasında değiştirmek tek tuş).

Adil olmak lazım, Java ile başta bahsettiğim projeye girişmeden önce, bunların farkında değildim. Python ile ise bu boyutta bir proje yapmadım. Küçük küçük bir sürü script(ki her biri, yazdığım satır sayısına göre işimi abartı derecede kolaylaştırıyor), en büyük projem kendi blogum.

Python bana programlamaya ilk başladığım günlerde bile birşeyler üretme imkanı verdi. Programlamaya başladığım sene(lisede yaptığım web tasarım + programlamayı saymıyorum), ilk önce kendi blogumu, daha sonra arşiv düzenleyiciyi yapabildim. Başka bir dille yapamazdım.

Şu anda static typed bir dilin bana sağladıklarını biliyorum(en azından bu projeleri yapmaya başlamadan öncekine göre çok daha iyi biliyorum). Şimdi dynamic typed bir dilin avantajlarını görmem lazım.

O yüzden IRC istemcimi her şeye rağmen Python ile yazacağım. Java ile yazarsam, kendimi tekrar etmekten başka birşey yapmamış olacağım. Twisted'ı ihtiyacım olduğu kadarıyla öğrenmeye bugün başlıyorum. Çalıştırılabilir bir hale gelir gelmez yorumlarımı buraya yazacağım.

(Bu arada Twisted'da IRC istemci protokolü hazır olarak var)

VIM hakkında

Vim hakkında da birkaç birşey söyleyeyim hazır IDE/Editor muhabbetine girmişken. Yaklaşık 7-8 aydır(sanırım) Vim kullanıyorum, ve şu dakikadan sonra Vim'siz hiçbir şey yazamaz oldum. Maillerimi Vim ile yazıyorum(sylpheed), bloga yazıları Vim ile giriyorum(kendi eklentim), Eclipse'de Vim eklentisi kullanıyorum(o olmasa Eclipse kullanamazdım), Lisp ile uğraştığımda, Emacs kullanmam gerekiyor ve Emacs'i vimpulse ile kullanıyorum. Şöyle iyi böyle güzel diye anlatmayacağım, resmen bağımlı oldum. Arkadaşların, normal IDE/Editorlerde nasıl yazdıklarını görünce duygulu anlar yaşıyorum.

Bu yüzden IDE seçerken dikkat ettiğim konulardan biri de Vim desteği(veya eklentileri) oluyor. Eclipse o açıdan(viPlugin sağolsun) çok başarılı. Söz konusu Java olduğunda düşünüyorum da, Eclipse olmasa herhalde hiçbir şey yazamazdım.(bu arada WingIDE Vim tuşlarını destekliyormuş, ne kadar başarılıdır bilmiyorum)

Pardus'ta dropbox, VIM + exuberant ctags ve bir hata kaydı

13-4-2011, 4:38 ö.s. // yorum // vim , pardus

~20 gün boyunca Pardus'tan başka işletim sistemi kullanmama gibi çılgın bir karar aldım ve bugün uygulamaya başladım(dün gece temiz kurulum + devel deposu güncellemelerini yapmıştım). İlk günün sonundan birkaç not düşelim:

  • Dropbox kullanmak isteyenler için, paket şu adreste: http://svn.pardus.org.tr/pardus/playground/maidis/Dropbox/dropbox/ . sudo pisi bi http://svn.pardus.org.tr/pardus/playground/maidis/Dropbox/dropbox/pspec.xml ile build eder, sudo pisi it dropbox*.pisi ile kurarsınız. Daha sonra ne işe yaradığını tam bilmesem de(ben direkt ikisini beraber kurduğumdan farkı gözlemleyemedim) http://svn.pardus.org.tr/pardus/playground/maidis/Dropbox/kde-servicemenu-dropbox/ adresinden KDE servicemenu eklentisini kursanız hoş olur. Yöntem aynı.

  • Vim ile ctags kullanmak isterseniz, package manager ile kurduğunuz ctags'ı görmüyor vim. Ctags paketini incelediğimde şöyle birşey satır gördüm: (satır 24) pisitools.rename("/usr/bin/ctags", "exuberant-ctags"). Farkedilebileceği gibi /usr/bin altındaki ctags çalıştırılabilirinin adı exuberant-ctags olarak değiştiriliyor. Bunu eski haline getirirseniz vim ile gayet düzgün çalışıyor.(ben adını değiştirmek yerine kopyaladım, iki tane oldu, heheh)

  • Hayırlısıyla bir de şöyle bir hata kaydımız oldu ilk günden: http://bugs.pardus.org.tr/show_bug.cgi?id=17765

Bu 20 gün içerisinde Emacs için SLIME pisi paketi hazırlama gibi çılgın bir hedefim var ayrıca. Başarabilirsem paket hazırlama olayını çözdüğüm anlamına gelecek.

Çalışan bir Python programına mesaj gönderme ve PyGTK

17-3-2011, 6:21 ö.ö. // yorum // python , vim

Bloguma vim ile yazı yazma projemin bir parçası(aslında vim ile python scripti çağırmak ile alakalı yaptığım deneylerin bir sonucu olan) olan vim-markdown-preview scriptin sayesinde birkaç şey farkettim.

Vim için bir script yazacaksanız ve bu scriptin tek yapacağı buffer'daki metini alıp onunla birşeyler yapmaksa, bunun en basit yolu bir vimscriptiyle buffer'ı başka bir python scriptine göndermek sanırım. En azından ben öyle yaptım. Şu kadar basit:

function! MarkdownPreview()

python << EOF

import vim
import subprocess

gr = "/home/osa1/Desktop/vim-markdown-preview/GeckoRenderer.py"
subprocess.Popen(["python", gr, "\n".join(vim.current.buffer[:])])

EOF
endfunction

Burda farkedebileceğiniz gibi bufferı çekip, subprocess.Popen ile istediğiniz Python scriptine gönderebiliyorsunuz. Çok kolay, bundan sonrası da normal Python zaten.

Fakat burda şöyle bir problem oluşuyor, bu fonksiyonu her çağırdığınızda Python scripti bir daha çalışıyor. Benim yapmak istediğim, eğer script zaten çalışıyorsa onu güncellemek.

Burda iki problem var, birincisi, programın zaten çalışıp çalışmadığını tespit etmek, ikincisi de eğer zaten çalışıyorsa ona mesaj göndermek. İkisi hakkında da nette bir sürü çözüm var(dbus, pid, multiprocess, pipe, alakalı SO mesajları: 1, 2, 3, 4).

Fakat benim uyguladığım ve sanırım en basit yöntem, programın çalışmadan önce bir dosyayı kontrol etmesi, o varsa çalışmak yerine gerekli sunucunun(localhost) gerekli portuna mesaj göndermesi. Mesajlaşma olayını socketlerle hallettim yani. Çok kolay ve anlaşılır oldu. Fakat işin içine arayüz girince bir problem daha ortaya çıktı: bir socket dinlerken arayüzü güncellemek.

Aşağıdaki program herşeyi özetliyor:

import os
import gtk
import socket
import gobject
from sys import argv

# dosya adi farketmez, programimiza ait oldugu belli olsun
PIDFILE = "ohnoes.pid"
PORT = 8081 # dinleyecegimiz port, musait bir port olsun yeter
DELAY = 1

def run(text):
    # burda birseyler yapilacak
    port = PORT
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # udp
    s.bind(("", port)) # localhost'da 8081'i dinleyecegiz
    # burasi onemli, DELAY surede bir dinlemeyi birakip,
    # arayuzu guncellenmeye zorlayacagiz
    s.settimeout(DELAY) 
    while True:
        try:
            data, addr = s.recvfrom(1024)  # dinleme
        except socket.timeout:  # delay sure bekledik, birsey yok
            print "timeout"
        else:
            print "got data", str(data)  # veriyi aldik
            update(data)  # guncelleme fonksiyonumuzu cagirdik

        # bu sekilde gtk'yi guncellenmeye zorluyoruz
        while gtk.events_pending():
            gtk.main_iteration()
        # surekli True dondurerek gtk'ya islemin bitmedigini soyluyoruz
        # musait oldugunda yine bu fonksiyonu cagirsin
        yield True

def is_running():
    # Pid'e falan hic gerek yok,
    # bir dosya olusturup, onu kontrol edecegiz
    # program acilirken o dosyayi olusturacak,
    # kapanirken silecek, sorun yok
    if os.path.isfile(PIDFILE):
        return True # program zaten calisiyor
    with file(PIDFILE, "w") as f:
        f.write("running")  # dosyanin icerigi onemli degil
    return False

if __name__ == "__main__":
    text = argv[1]
    if is_running(): # program calisiyor
        port = PORT
        host = "localhost"
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # udp
        s.bind(("", 0))
        s.sendto(text, (host, port))  # veriyi gonder
    else:
        # bu asamaya gelindiginde, is_running() zaten gerekli
        # dosyayi olusturmus oluyor
        task = run(text)  # program calistiriliyor
        gobject.idle_add(task.next)  # gtk musait oldugunda bunu cagiracak
        gtk.main()

Kodda bulunmayan ama dikkat edilmesi gerek bir nokta da, gui'nin kapanma fonksiyonuna(close sinyali gönderildiğinde çağırılan fonksiyon) os.remove(PIDFILE) satırını eklenmesi. Ha unutmadan, dosya konumu değiştirilmeli tabii ki, bu halde program halgi dizinden çağırılıyorsa oraya bakıyor ve gerekiyorsa dosyayı oluşturuyor.

Ubuntu'da custom keyboard layout

15-3-2011, 9 ö.ö. // yorum // vim

Vim ile uğraştığım son birkaç ayda kendime çok sağlam bir .vimrc dosyası hazırladım. Bir sürü ayar var ama benim için en önemli kısımları, sistem genelinde ihtiyaç duyduğum map ğ [ map ü ] map Ğ { ve map Ü } kısımları. Dizüstü bilgisyarımın klavyesi ingilizce ve ordan farkettim, ingilizce klavyede ğ ve ü'nün olduğu yerlerde [ ] var ve çok daha kullanışlı.

Kod yazarken türkçe karakterleri hiçbir şekilde kullanmadığımıza göre, bunları bir şekilde [] ile değiştirebilirsem çok daha kullanışlı olacak. Türkçe klavyede []{} karakterlerinin yerleri çok kötü. (vim'de { } karakterleri normal mode'da bloklar arasında gezinmeyi de sağlıyor.)

Küçük bir araştırmayla nasıl olacağını buldum. Not olsun, buraya yazıyorum(diğer bilgisayarda da yapılacak).

Klavye düzenleri /usr/share/X11/xkb/symbols adresinde tutuluyor. Burdaki tr bizim kullandığımız türkçe klavye. Bizim yapmak istediğimiz ondaki sadece 2 satırı değiştirmek olduğundan, tüm dosyayı kopyalayıp adını istediğimiz bir şekilde değiştiriyoruz(ben t1 yaptım). Daha sonra içini açıp şu satırları buluyoruz.

key <AD11>  {[gbreve, Gbreve ]};
key <AD12>  {[udiaeresis, Udiaeresis, asciitilde, dead_macron]};

Bu iki satır ğ ve ü harflerini temsil ediyor, [] arasındaki ikinci kısım, shift+tuş şeklinde basıldığında vereceği karakter. Şu şekilde değiştiriyoruz:

key <AD11>  {[bracketleft, braceleft ]};
key <AD12>  {[bracketright, braceright, asciitilde, dead_macron]};

Bu kadar. Kaydedip çıktıktan sonra başka bir dosyada daha değişiklik yapacağız. /usr/share/X11/xkb/rules/evdav.xml dosyasını açıyoruz. Herhangi bir </layout> sonuna şunu ekliyoruz:

<layout> <!-- custom -->
    <configItem>
        <name>t1</name> <!-- buraya dosyanizin adi gelecek -->
        <shortDescription>t1</shortDescription> <!-- bu satir gnome panelde de gozukecek -->
        <description>My Custom Layout 1</description>
        <languageList><iso639Id>tur</iso639Id></languageList>
    </configItem>
    <variantList/>
</layout>

Bu kadar. Bundan sonra gnome-keyboard-propertiesi çalıştırıp klavye düzenimizi ekliyoruz. Burda klavye düzenlerini hızlıca değiştirmek için ayar ekranından shift + ctrl vb. şeyler seçebilirsiniz.

0 , 1