29.6.06

Elisp ile dosya calistirma

Emacs'da bir dosyayi calistirip, ciktisini yeni bir buffer'da gormek icin yazdigim bir script. Buradan da kopya cektim biraz. Eminim ki tekeri bastan icad ediyorum, hem de kagni tekeri (aklima bunu getirdi). Ama kucuk olsun benim olsun :) Bir de hala su degiskenlere dogru duzgun isim vermeyi ogrenemedim. Zamanimin yarisi bunu ne diye adlandirayim diye geciyor.

Not: daha duzgun degisken isimleri vermeye calistim.

; a list of triples that contain:
;  - the regex for the file name
;  - the name of the buffer that will be created
;  - a list containing the command to execute the file
(defvar exec-list nil)

(defun add-exec (regex buffer-name command-list)
  (let ((entry (list regex buffer-name command-list)))
    (setf exec-list (cons entry exec-list))))

(defun get-exec-help (filename execs)
  (unless (null execs)
    (let* ((entry (car execs))
       (regex (car entry)))
      (if (string-match regex filename)
      (cdr entry)
    (get-exec-help filename (cdr execs))))))

(defun get-exec (filename)
  (get-exec-help filename exec-list))


(defun exec-file () 
  "Execute a file, if possible."
  (interactive)
  (let* ((curr-buf (buffer-name))
     (exec-params (get-exec curr-buf)))
    (if exec-params
    (let ((exec-buffer (car exec-params))
          (exec-command-list (cadr exec-params)))
      (if (get-buffer exec-buffer) 
          (kill-buffer exec-buffer)
        (progn
          (eval (append
             (list 'start-process 
               exec-buffer
               exec-buffer)
             exec-command-list
             (list curr-buf)))
          (switch-to-buffer-other-window exec-buffer)
          (switch-to-buffer-other-window curr-buf)))))))

(add-exec "\\.js$" 
      "javascript" 
      (list "/usr/bin/rhino" "-f"))

(add-exec "\\.\\(pir\\|pasm\\)$" 
      "parrot" 
      (list "/home/yavuz/parrot_svn/parrot/parrot"))

(add-exec "\\.html$" 
      "html" 
      (list "/usr/bin/firefox"))

(global-set-key [f12] 'exec-file)

31.5.06

Iyi huylu böcek

Ruby ile yazdigim basit bir programda kullanicinin attigi her adim @lines adinda bir listede tutuluyor. Kullanici istedigi zaman bu adimlari gorebiliyor, ve "undo <n>" diyerek <n>'inci siradaki adimi iptal edebiliyor. Kullanicinin kafasini karistirmamak icin <n> 1'den basliyor (her ne kadar bu programi benden baska hickimse kullanmayacak olsa da :-) ). Iptal edici fonksiyon soyle birsey:

def undo(line)
    n = line.gsub(/undo\W+([^\W]*)/, '\1').to_i
    @lines.delete_at(n-1)
    rescue print("You did not give a valid line number!\n")
end

Daha sonra kullanici sadece "undo" yazdigi takdirde en son yaptigi islemin iptal edilmesinin faydali olacagini dusundum. Bunu programlamadan once su anda bu durumda ne oluyor bir bakayim dedim. Cok garip: tam da istedigim sey oluyordu.

Ben bir sayi ifade etmeyen bir string'e to_i metodu uygulandiginda hata firlatacagini dusunuyordum, fakat 0 donduruyormus. Yani kullanici "undo" komutunu verdiginde gsub'un sonucu regex uymadigi icin yine "undo" oluyor, onun da to_i metodu 0 donduruyor. Bir sonraki satirda @lines.delete(-1) ifadesi calisiyor, yani @lines'in son elemani siliniyor :)

Keske butun bocekler de bunun gibi olsa... demiyorum, bocegin gizlenmeyeni makbuldur.

29.4.06

Emacs notlari

Bir ogrendigimi fazla kullanmayinca kisa sure icerisinde unutuyorum. Bu da bilgi bir daha gerektiginde zaman kaybina neden oluyor. Not tutmaya karar verdim.
Buraya emacs notlarimi yazayim:

  • C-h k : tus kombinasyonunun hangi komutu calistirdigini ogrenmek
  • C-x ({ | }) : (enlarge | shrink)-window-horizontally
  • C-x ^ : enlarge window
  • C-x C-e : evaluate lisp expression

 

not: Rickdangerous'un tavsiyesi uzerine kopya cekmeye karar verdim. Isime de geldi. Ne de olsa ben tembel bir adamim.

25.4.06

xmms-ruby

fazlamesai.net'ten FZ ruby ile emacs icinden xmms'e parca sectiren bir program yazmis. Hazir ruby tutorial'ini biraz karistirmisken ruby ile birseyler yapayim dedim. Programi biraz daha gelistirdim.
Ekledigim seyler:
  • Birden fazla kelime aranabiliyor, hepsinin parca ismine/dosya ismine uymasi lazim
  • Sadece sayi girilirse xmms o siradaki parcaya atliyor
  • Girdi ':' ile baslarsa xmms'e direkt ruby kodu ile hukmedebiliyoruz (:stop, :play :next gibi). eval fonksiyonu sagolsun.
  • Eger ilk arguman --dialog ise girdi bir dialog yardimiyla aliniyor.
Ben gconf-editor yardimiyla C-M-j tus kombinasyonunu --dialog opsiyonuna atadim. Biraz yavas da olsa idare ediyor. Aslina bakarsaniz bunu zaten birinin yapmis olabilecegini dusunup kisa bir aramadan sonra xmmsfind'i buldum, fakat ne yazik ki cani istemedigi zaman acilmama gibi bir sorunu var.
#!/usr/bin/env ruby

require 'xmms'

def nextSong(args, xr) 
  matching = []
  i = 0
  xr.playlist.each do |entry|
    if match(entry, args) 
      matching << i
      $stderr.puts 'Matched: ' + entry[0]
    end
    i += 1
  end
  if matching.length == 0
    return false
  else
    xr.position = matching[rand(matching.length)]
    return true
  end
end

def match(entry, args) 
  title, file, time = entry
  args.each do |arg|
    regex = /#{arg}/i
    return false unless (title =~ regex or file =~ regex)
  end
  return true
end

def is_int(str)
  return str =~ /^[0-9]+$/
end


$stderr.puts 'Xmms-Ruby version ' << Xmms::Remote::VERSION

# allocate a new Xmms::Remote object
xr = Xmms::Remote::new

if ARGV.length == 1 and ARGV[0] == '--dialog'
  cmd = open('| zenity --entry --text "xmms: give some keywords"')
  argStr = cmd.gets.strip
  args = argStr.split
  cmd.close
  puts args.to_s
  exit if args.length == 0
else
  argStr = ARGV.map{|s| s.strip}.join(' ')
  args = argStr.split
end

if args.length == 0
  xr.next
  $stderr.puts 'next song'
elsif is_int(argStr) and argStr.to_i <= xr.playlist.length and argStr.to_i > 0
  xr.position = argStr.to_i - 1
  $stderr.puts 'jump to position: ' + argStr
elsif argStr[0] == ":"[0]
  $stderr.puts 'Evaluate: ' + argStr[1..-1]
  eval ('xr.' + argStr[1..-1])
elsif not nextSong(args, xr)
  $stderr.puts 'No match: ' +  argStr
end