Thursday, March 23, 2006

emacs+ruby, scheme

ผมเคยเขียน Customize Syntax Highlight
ด้วย Ruby ไปที
ตอนนั้นใช้ Ruby Syntax 1.0.0 ช่วยทำ

วันนี้มีเหตุให้ปัดฝุ่นกลับมาใช้อีกครั้ง
แต่คราวนี้มาในรูปแบบพิสดารกว่าเดิม
เป้าหมายในคราวนี้คือ

ตัวโปรแกรมจะ parse ruby code
output ที่ได้จะอยู่ในรูป scheme code
(syntax highlight ในรูปแบบ scheme code)
โดยโปรแกรมต้องสามารถเรียกจาก emacs ได้โดยตรง

ตัวโปรแกรม ruby เขียนไม่ยาก
แค่ extend Syntax::Convertors::Abstract
class Ruby2SS < Syntax::Convertors::Abstract

def convert(text)
str = "(page-para (code-block (code-line "
regions = []
@tokenizer.tokenize(text) do |tok|
str << to_scheme(tok)
end
str << ')))'
end

def to_scheme(tok)
case tok.group
when :punct :
if tok =~ /"|'/
"(code 'punct \"\\#{tok}\")\n"
else
"(code 'punct \"#{tok}\")\n"
end
when :normal :
if tok =~ /[^\n]*\n([^\n]*)/
")\n (code-line (code 'normal \"#{$1}\") \n"
else
"(code 'normal \"#{tok}\")\n"
end
else
"(code '#{tok.group} \"#{tok}\")\n"
end
end

end


code ที่ได้หน้าตาแบบนี้
(page-para (code-block 
(code-line (code 'ident "order")
(code 'normal " ")
(code 'punct "=")
(code 'normal " ")
(code 'constant "Order")
(code 'punct ".")
(code 'ident "new")
)
(code-line (code 'normal "")
(code 'ident "order")
(code 'punct ".")
(code 'ident "name")
(code 'normal " ")
(code 'punct "=")
(code 'normal " ")
(code 'punct "\"")
(code 'string "")
(code 'string "pok")
(code 'string "")
(code 'punct "\"")
)))


ซึ่งจะเอาไป output ออกเป็น image อีกที (ไม่ขอพูดถึงตอนนี้)

เวลาใช้ก็ต้อง integrate เข้ากับ emacs
โดยผมเลือกเอา el4r มาใช้
โดยต้องเขียน function ขึ้นมา 2 ตัว
ตัวแรกเป็น ruby function ที่อยู่ใน form ที่ emacs สามารถ call ได้
defun(:ruby_syntax_to_scheme,
:interactive => false) { |code|
Ruby2SS.new(Syntax::load('ruby')).convert code
}

ส่วนอีกตัว ก็คือ elisp ที่ทำหน้าที่ดึงข้อมูลจาก buffer แล้วส่งต่อ
ให้ ruby function จากนั้นก็นำผลลัพท์ไปใส่ไว้ใน clipboard
(defun cv-ruby-syntax-to-scheme-slide (beg end)
(interactive "r")
(let ((str (filter-buffer-substring beg end))
(x-select-enable-clipboard t))
(kill-new (ruby-syntax-to-scheme str) 'replace)))
(define-key ruby-mode-map "\C-c\C-p" 'cv-ruby-syntax-to-scheme-slide)


(จริงๆเขียนฝั่ง ruby ตัวเดียวก็ได้ แต่ขึ้เกียจ debug หรือ หัดใช้ el4r มากกว่านี้
ก็เลยเอาแค่ทำงานได้)

Related link from Roti

No comments: