Thursday, August 6, 2009

Cách thay đổi màu cho keyword trong gvim

Trong bài viết này mình sẽ huớng dẫn cách thay đổi màu cho keyword đồng thời chúng ta có thể add thêm keyword vào trong một colorscheme nào đó trong gvim.
Thật ra thì gvim có rất nhiều colorscheme cũng đẹp, tuy vậy nó cũng chỉ là mặc định theo một theme nào đó mà thôi, nhiều khi ta muốn thêm keyword cho GTK+, hay openGL hay STL thì chúng ta cũng không thể dùng các colorscheme đó được vì vậy cách tốt nhất là chỉnh sữa thủ công. Tuy là cách này hơi tốn thời gian một tí nhưng chúng ta sẽ có các keyword mà chúng ta ưng ý nhất :D !
- Để chỉnh sữa màu cho một colorsheme nào đó thì chúng ta phải chỉnh sữa các file sau đây, lưu ý là trong ví dụ này mình sẽ chọn syntax cho các file .cpp vì mình ngôn ngữ lập trình chính của mình là C++.
Đầu tiên chúng ta sẽ link tới các folder sau :

/usr/share/vim/vim72

Trong folder này chúng ta sẽ thấy các file :

autoload evim.vim indent mswin.vim synmenu.vim
bugreport.vim filetype.vim indent.vim optwin.vim syntax
colors ftoff.vim indoff.vim plugin tools
compiler ftplugin keymap print tutor
debian.vim ftplugin.vim lang rgb.txt vimrc_example.vim
delmenu.vim ftplugof.vim macros scripts.vim
doc gvimrc_example.vim menu.vim spell

Trong folder này thì cái mà chúng ta cần lưu ý là 2 folder : colors và syntax. Vì trong 2 folder này sẽ chứa tất cả các colorsheme ( colors folder ) và tất cả các syntax của các ngôn ngữ ( syntax folder ) :
Trong folder colors chúng ta có các file sau :

blue.vim delek.vim evening.vim murphy.vim README.txt slate.vim
darkblue.vim desert.vim koehler.vim pablo.vim ron.vim torte.vim
default.vim elflord.vim morning.vim peachpuff.vim shine.vim zellner.vim

Chúng ta có thể dễ dàng thấy rằng đây là các colorscheme mà chúng ta thuờng dùng. Ở đây mình sẽ chọn colorscheme "delek.vim", việc chọn file này là vì nó có background color là màu trắng và các keyword của nó màu cũng tương tự như màu mặc định và điều này sẽ làm cho chúng ta dễ dàng hơn trong việc chỉnh sữa và sử dụng lại.

Bây giờ ta mở file delek.vim lên :

" Vim color file
" Maintainer: David Schweikert
" Last Change: 2006 Apr 30

hi clear

let colors_name = "delek"

" Normal should come first
hi Normal guifg=Black guibg=#FFFFFF
hi Cursor guifg=bg guibg=fg
hi lCursor guifg=NONE guibg=Cyan

" Note: we never set 'term' because the defaults for B&W terminals are OK
hi DiffAdd ctermbg=LightBlue guibg=LightBlue
hi DiffChange ctermbg=LightMagenta guibg=LightMagenta
hi DiffDelete ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan
hi DiffText ctermbg=Red cterm=bold gui=bold guibg=Red
hi Directory ctermfg=DarkBlue guifg=Blue
hi ErrorMsg ctermfg=White ctermbg=DarkRed guibg=Red guifg=White
hi FoldColumn ctermfg=DarkBlue ctermbg=Grey guibg=Grey guifg=DarkBlue
hi Folded ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue
hi IncSearch cterm=reverse gui=reverse
hi LineNr ctermfg=Brown guifg=Brown
hi ModeMsg cterm=bold gui=bold
hi MoreMsg ctermfg=DarkGreen gui=bold guifg=SeaGreen
hi NonText ctermfg=Blue gui=bold guifg=gray guibg=white
hi Pmenu guibg=LightBlue
hi PmenuSel ctermfg=White ctermbg=DarkBlue guifg=White guibg=DarkBlue
hi Question ctermfg=DarkGreen gui=bold guifg=SeaGreen
hi Search ctermfg=NONE ctermbg=Yellow guibg=Yellow guifg=NONE
hi SpecialKey ctermfg=DarkBlue guifg=Blue
hi StatusLine cterm=bold ctermbg=blue ctermfg=yellow guibg=gold guifg=blue
hi StatusLineNC cterm=bold ctermbg=blue ctermfg=black guibg=gold guifg=blue
hi Title ctermfg=DarkMagenta gui=bold guifg=Magenta
hi VertSplit cterm=reverse gui=reverse
hi Visual ctermbg=NONE cterm=reverse gui=reverse guifg=Grey guibg=fg
hi VisualNOS cterm=underline,bold gui=underline,bold
hi WarningMsg ctermfg=DarkRed guifg=Red
hi WildMenu ctermfg=Black ctermbg=Yellow guibg=Yellow guifg=Black

" syntax highlighting
hi Comment cterm=NONE ctermfg=DarkRed gui=NONE guifg=#A020F0
hi Constant cterm=NONE ctermfg=DarkGreen gui=NONE guifg=#02A602
hi Identifier cterm=NONE ctermfg=DarkCyan gui=NONE guifg=cyan4
hi PreProc cterm=NONE ctermfg=DarkMagenta gui=NONE guifg=#A52A2A
hi Special cterm=NONE ctermfg=LightRed gui=NONE guifg=deeppink
hi Statement cterm=bold ctermfg=Blue gui=bold guifg=black
hi Type cterm=NONE ctermfg=Blue gui=bold guifg=black
hi GtkKeyword cterm=NONE ctermfg=Red gui=bold guifg=red
hi StlKeyword cterm=NONE ctermfg=NONE gui=bold guifg=#1E90FF
" vim: sw=2


Lưu ý là cái file này không còn là file nguyên thuỷ của ban đầu nữa, vì mình đã thêm một số keyword vào cho nó rồi. Và chúng ta có 2 dòng phải chú là :

hi GtkKeyword cterm=NONE ctermfg=Red gui=bold guifg=red
hi StlKeyword cterm=NONE ctermfg=NONE gui=bold guifg=#1E90FF

Đây là 2 dòng mình đã thêm vào, lưu ý một điều là để chỉnh sữa phải này thì chúng ta phải có đặc quyền root, vì vậy ví dụ để mở file delek.vim thì ta dùng command line sau : ( thêm vào sudo )

sudo gvim delek.vim

Và chúng ta cần ý 2 cái tên mà ta đã thêm vào GtkKeyword và StlKeyword. Hai cái tên này là do chúng ta đặt ra vì vậy các bạn muốn chỉnh sữa thế nào là tuỳ. Và đến lúc này chúng ta sẽ hơi khó hiểu ^_^ vì không biết làm sao gvim nó hiểu tiếng Anh đây! Và đến lúc này thì ta cần phải chỉnh sữa thêm thằng bạn của nó. Và thằng "bạn" của nó sẽ nằm trong folder "syntax" và có tên là cpp.vim.
Giả sử chúng ta ở đang ở trên folder chính là vim72 thì ta sẽ vào trực tiếp "syntax" folder bằng câu lệnh đơn giản sau :

cd syntax

Và đuờng dẫn của nó là :

chan@chan-laptop:/usr/share/vim/vim72$ cd syntax

Dòng này là dòng mình copy nguyên si từ terminal của mình.
Và trong folder này nó sẽ có các file sau :

2html.vim elmfilt.vim master.vim sgmldecl.vim
a2ps.vim erlang.vim matlab.vim sgmllnx.vim
a65.vim eruby.vim maxima.vim sgml.vim
aap.vim esmtprc.vim mel.vim sh.vim
abap.vim esqlc.vim messages.vim sicad.vim
abaqus.vim esterel.vim mf.vim sieve.vim
abc.vim eterm.vim mgl.vim simula.vim
abel.vim eviews.vim mgp.vim sindacmp.vim
acedb.vim exim.vim mib.vim sindaout.vim
ada.vim expect.vim mma.vim sinda.vim
aflex.vim exports.vim mmix.vim sisu.vim
ahdl.vim fasm.vim mmp.vim skill.vim
alsaconf.vim fdcc.vim modconf.vim slang.vim
amiga.vim fetchmail.vim model.vim slice.vim
aml.vim fgl.vim modsim3.vim slpconf.vim
ampl.vim flexwiki.vim modula2.vim slpreg.vim
antlr.vim focexec.vim modula3.vim slpspi.vim
ant.vim form.vim monk.vim slrnrc.vim
apachestyle.vim forth.vim moo.vim slrnsc.vim
apache.vim fortran.vim mplayerconf.vim sl.vim
arch.vim foxpro.vim mp.vim smarty.vim
art.vim framescript.vim mrxvtrc.vim smcl.vim
asm68k.vim freebasic.vim msidl.vim smil.vim
asmh8300.vim fstab.vim msmessages.vim smith.vim
asm.vim fvwm2m4.vim msql.vim sml.vim
asn.vim fvwm.vim mupad.vim sm.vim
aspperl.vim gdb.vim mush.vim snnsnet.vim
aspvbs.vim gdmo.vim muttrc.vim snnspat.vim
asterisk.vim gedcom.vim mysql.vim snnsres.vim
asteriskvm.vim gitcommit.vim named.vim snobol4.vim
atlas.vim gitconfig.vim nanorc.vim specman.vim
autohotkey.vim gitrebase.vim nasm.vim spec.vim
autoit.vim gitsendemail.vim nastran.vim spice.vim
automake.vim git.vim natural.vim splint.vim
ave.vim gkrellmrc.vim ncf.vim spup.vim
awk.vim gnuplot.vim netrc.vim spyce.vim
ayacc.vim gpg.vim netrw.vim sqlanywhere.vim
baan.vim gp.vim nosyntax.vim sqlforms.vim
basic.vim grads.vim nqc.vim sqlinformix.vim
bc.vim gretl.vim nroff.vim sqlj.vim
bdf.vim groff.vim nsis.vim sqloracle.vim
bib.vim groovy.vim objcpp.vim sql.vim
bindzone.vim group.vim objc.vim sqr.vim
blank.vim grub.vim ocaml.vim squid.vim
bst.vim gsp.vim occam.vim sshconfig.vim
btm.vim gtkrc.vim omnimark.vim sshdconfig.vim
b.vim haml.vim openroad.vim stata.vim
bzr.vim hamster.vim opl.vim stp.vim
calendar.vim haskell.vim ora.vim strace.vim
catalog.vim hastepreproc.vim pamconf.vim st.vim
cdl.vim haste.vim papp.vim sudoers.vim
cdrdaoconf.vim hb.vim pascal.vim svn.vim
cdrtoc.vim help.vim passwd.vim syncolor.vim
cfg.vim hercules.vim pcap.vim synload.vim
cf.vim hex.vim pccts.vim syntax.vim
changelog.vim hitest.vim pdf.vim sysctl.vim
change.vim hog.vim perl.vim tads.vim
chaskell.vim hostconf.vim pfmain.vim tags.vim
cheetah.vim htmlcheetah.vim pf.vim takcmp.vim
chill.vim htmldjango.vim php.vim takout.vim
chordpro.vim htmlm4.vim phtml.vim tak.vim
ch.vim htmlos.vim pic.vim tar.vim
clean.vim html.vim pike.vim tasm.vim
clipper.vim ia64.vim pilrc.vim tcl.vim
cl.vim ibasic.vim pine.vim tcsh.vim
cmake.vim icemenu.vim pinfo.vim terminfo.vim
cmusrc.vim icon.vim plaintex.vim texinfo.vim
cobol.vim idlang.vim plm.vim texmf.vim
coco.vim idl.vim plp.vim tex.vim
colortest.vim indent.vim plsql.vim tf.vim
conaryrecipe.vim inform.vim pod.vim tidy.vim
config.vim initex.vim postscr.vim tilde.vim
conf.vim initng.vim po.vim tli.vim
context.vim inittab.vim povini.vim tpp.vim
cpp.vim ipfilter.vim pov.vim trasys.vim
crm.vim ishd.vim ppd.vim trustees.vim
crontab.vim iss.vim ppwiz.vim tsalt.vim
csc.vim ist.vim prescribe.vim tsscl.vim
csh.vim jal.vim privoxy.vim tssgm.vim
csp.vim jam.vim procmail.vim tssop.vim
css.vim jargon.vim progress.vim uc.vim
cs.vim javacc.vim prolog.vim udevconf.vim
cterm.vim javascript.vim promela.vim udevperm.vim
ctrlh.vim java.vim protocols.vim udevrules.vim
cuda.vim jess.vim psf.vim uil.vim
cuplsim.vim jgraph.vim ptcap.vim updatedb.vim
cupl.vim jproperties.vim purifylog.vim valgrind.vim
c.vim jsp.vim pyrex.vim vb.vim
cvsrc.vim kconfig.vim python.vim vera.vim
cvs.vim kix.vim qf.vim verilogams.vim
cweb.vim kscript.vim quake.vim verilog.vim
cynlib.vim kwt.vim racc.vim vgrindefs.vim
cynpp.vim lace.vim radiance.vim vhdl.vim
dcd.vim latte.vim ratpoison.vim viminfo.vim
dcl.vim ldapconf.vim rcslog.vim vim.vim
debchangelog.vim ldif.vim rcs.vim virata.vim
debcontrol.vim ld.vim rc.vim vmasm.vim
debsources.vim lex.vim readline.vim voscm.vim
def.vim lftp.vim README.txt vrml.vim
denyhosts.vim lhaskell.vim rebol.vim vsejcl.vim
desc.vim libao.vim registry.vim wdiff.vim
desktop.vim lifelines.vim remind.vim webmacro.vim
dictconf.vim lilo.vim resolv.vim web.vim
dictdconf.vim limits.vim reva.vim wget.vim
diff.vim lisp.vim rexx.vim whitespace.vim
dircolors.vim litestep.vim rhelp.vim winbatch.vim
diva.vim lite.vim rib.vim wml.vim
django.vim loginaccess.vim rnc.vim wsh.vim
dns.vim logindefs.vim rnoweb.vim wsml.vim
docbksgml.vim logtalk.vim robots.vim wvdial.vim
docbk.vim lotos.vim rpcgen.vim xbl.vim
docbkxml.vim lout.vim rpl.vim xdefaults.vim
dosbatch.vim lpc.vim rst.vim xf86conf.vim
dosini.vim lprolog.vim rtf.vim xhtml.vim
dot.vim lscript.vim ruby.vim xinetd.vim
doxygen.vim lsl.vim r.vim xkb.vim
dracula.vim lss.vim samba.vim xmath.vim
dsl.vim lua.vim sass.vim xml.vim
dtd.vim lynx.vim sas.vim xmodmap.vim
dtml.vim m4.vim sather.vim xpm2.vim
dtrace.vim mailaliases.vim scheme.vim xpm.vim
d.vim mailcap.vim scilab.vim xquery.vim
dylanintr.vim mail.vim screen.vim xsd.vim
dylanlid.vim make.vim sdl.vim xslt.vim
dylan.vim manconf.vim sd.vim xs.vim
ecd.vim manual.vim sed.vim xxd.vim
edif.vim man.vim sendpr.vim yacc.vim
eiffel.vim maple.vim sensors.vim yaml.vim
elf.vim masm.vim services.vim z8a.vim
elinks.vim mason.vim setserial.vim zsh.vim


Nhưng cái mà mình quan tâm ở đây chỉ là thằng "cpp.vim", cái đám còn lại thì chúng ta không cần quan tâm. Nhưng nếu bạn là một lập trình viên Java hay bất cứ ngôn ngữ nào đó thì các bạn có thể chọn file của ngôn ngữ đó mà chỉnh sữa. Thao tác nó cũng tương tự mà thôi.
Bây giờ chúng ta sẽ mở file cpp.vim lên ta sẽ thấy như sau :

" Vim syntax file
" Language: C++
" Maintainer: Ken Shan
" Last Change: 2002 Jul 15

" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif

" Read the C syntax to start with
if version < 600
so :p:h/c.vim
else
runtime! syntax/c.vim
unlet b:current_syntax
endif

" C++ extentions
syn keyword cppStatement new delete this friend using
syn keyword cppAccess public protected private
syn keyword cppType inline virtual explicit export bool wchar_t
syn keyword cppExceptions throw try catch
syn keyword cppOperator operator typeid
syn keyword cppOperator and bitor or xor compl bitand and_eq or_eq xor_eq not not_eq
syn match cppCast "\<\(const\|static\|dynamic\|reinterpret\)_cast\s*<"me=e-1
syn match cppCast "\<\(const\|static\|dynamic\|reinterpret\)_cast\s*$"
syn keyword cppStorageClass mutable
syn keyword cppStructure class typename template namespace
syn keyword cppNumber NPOS
syn keyword cppBoolean true false
syn keyword gtkKeyword GObject GInitiallyUnowned GtkObject GtkWidget GtkContainer GtkBin GtkWindow GtkDialog GtkAboutDialog GtkColorSelectionDialog GtkFileChooserDialog GtkFileSelection GtkFontSelectionDialog GtkInputDialog GtkMessageDialog GtkPageSetupUnixDialog GtkPrintUnixDialog GtkRecentChooserDialog GtkAssistant GtkPlug GtkAlignment GtkFrame GtkAspectFrame GtkButton GtkToggleButton GtkCheckButton GtkRadioButton GtkColorButton GtkFontButton GtkLinkButton GtkOptionMenu GtkScaleButton GtkVolumeButton GtkItem GtkMenuItem GtkCheckMenuItem GtkRadioMenuItem GtkImageMenuItem GtkSeparatorMenuItem GtkTearoffMenuItem GtkListItem GtkTreeItem GtkComboBox GtkComboBoxEntry GtkEventBox GtkExpander GtkHandleBox GtkToolItem GtkToolButton GtkMenuToolButton GtkToggleToolButton GtkRadioToolButton GtkSeparatorToolItem GtkScrolledWindow GtkViewport GtkBox GtkButtonBox GtkHButtonBox GtkVButtonBox GtkVBox GtkColorSelection GtkFileChooserWidget GtkFontSelection GtkGammaCurve GtkRecentChooserWidget GtkHBox GtkCombo GtkFileChooserButton GtkStatusbar GtkCList GtkCTree GtkFixed GtkPaned GtkHPaned GtkVPaned GtkIconView GtkLayout GtkList GtkMenuShell GtkMenuBar GtkMenu GtkRecentChooserMenu GtkNotebook GtkSocket GtkTable GtkTextView GtkToolbar GtkTree GtkTreeView GtkMisc GtkLabel GtkAccelLabel GtkTipsQuery GtkArrow GtkImage GtkPixmap GtkCalendar GtkCellView GtkDrawingArea GtkCurve GtkEntry GtkSpinButton GtkRuler GtkHRuler GtkVRuler GtkRange GtkScale GtkHScale GtkVScale GtkScrollbar GtkHScrollbar GtkVScrollbar GtkSeparator GtkHSeparator GtkVSeparator GtkHSV GtkInvisible GtkOldEditable GtkText GtkPreview GtkProgress GtkProgressBar GtkAdjustment GtkCellRenderer GtkCellRendererText GtkCellRendererAccel GtkCellRendererCombo GtkCellRendererSpin GtkCellRendererPixbuf GtkCellRendererProgress GtkCellRendererToggle GtkFileFilter GtkItemFactory GtkTooltips GtkTreeViewColumn GtkRecentFilter GtkAccelGroup GtkAccelMap AtkObject GtkAccessible GtkAction GtkToggleAction GtkRadioAction GtkRecentAction GtkActionGroup GtkBuilder GtkClipboard GtkEntryCompletion GtkIconFactory GtkIconTheme GtkIMContext GtkIMContextSimple GtkIMMulticontext GtkListStore GMountOperation GtkMountOperation GtkPageSetup GtkPrinter GtkPrintContext GtkPrintJob GtkPrintOperation GtkPrintSettings GtkRcStyle GtkRecentManager GtkSettings GtkSizeGroup GtkStatusIcon GtkStyle GtkTextBuffer GtkTextChildAnchor GtkTextMark GtkTextTag GtkTextTagTable GtkTreeModelFilter GtkTreeModelSort GtkTreeSelection GtkTreeStore GtkUIManager GtkWindowGroup GtkTooltip GtkPrintBackend GInterface GtkBuildable GtkActivatable GtkOrientable GtkCellEditable GtkCellLayout GtkEditable GtkFileChooser GtkTreeModel GtkTreeDragSource GtkTreeDragDest GtkTreeSortable GtkPrintOperationPreview GtkRecentChooser GtkToolShell
syn keyword stlKeyword vector list deque map multimap set multiset string stack iterator streambuf bitset ostream istream stringstream ostringstream istringstream const_iterator ifstream ofstream fstream

" The minimum and maximum operators in GNU C++
syn match cppMinMax "[<>]?"

" Default highlighting
if version >= 508 || !exists("did_cpp_syntax_inits")
if version < 508
let did_cpp_syntax_inits = 1
command -nargs=+ HiLink hi link
else
command -nargs=+ HiLink hi def link
endif
HiLink cppAccess cppStatement
HiLink cppCast cppStatement
HiLink cppExceptions Exception
HiLink cppOperator Operator
HiLink cppStatement Statement
HiLink cppType Type
HiLink cppStorageClass StorageClass
HiLink cppStructure Structure
HiLink cppNumber Number
HiLink cppBoolean Boolean
HiLink gtkKeyword GtkKeyword
HiLink stlKeyword StlKeyword
delcommand HiLink
endif

let b:current_syntax = "cpp"

" vim: ts=8


Và 2 dòng mà chúng ta cần chú ý là 2 dòng bắt đầu bằng :

syn keyword gtkKeyword ...

Sữ dụng cú pháp này chúng ta đã định nghĩa một tập các keywords khác cho các file .cpp. Lưu ý là cái dấu "..." là nơi chúng ta thêm các keyword vào đó. Mỗi keywords sẽ cách nhau một "space". Mình sẽ lấy thằng stlKeyword làm ví dụ vì nó cũng không có nhiều keyword lắm. Ví dụ :

syn keyword stlKeyword vector list deque map multimap set multiset string stack iterator streambuf bitset ostream istream stringstream ostringstream istringstream const_iterator ifstream ofstream fstream

Nhưng công việc vẫn chưa xong, thằng stlKeyword ở đây chỉ đóng vai trò như một alias cho thằng mà chúng ta đã thêm vào StlKeyword mà thôi. Lý do có thêm thằng alias này là vì trong vim nó sử dụng các comment, keyword như một danh từ chung cho toàn các ngôn ngữ, vì vậy để tái sử dụng thì chúng phải có các danh từ chung này. Ví dụ cho C++ ta có alias "cppStatement" cho Java ta có "javaStatement".... Nhưng khi chúng ta đến dòng này :

HiLink cppStatement Statement

Thì chúng ta hiểu ra rằng à !!! thì ra là vậy ^_^ !
Nhưng đối với StlKeyword và GtkKeyword thì nó chỉ tồn tại trong C/C++ mà thôi, vì vậy đặt thêm thằng alias cũng chẳng mang ý nghĩa gì nhiều lắm. Nhưng để cho giống cấu trúc của file syntax thì ta thêm vào vậy thôi. Lưu ý thằng alias toàn bộ là viết thường trong khi thằng chúng ta sử dụng sẽ có chữ cái Hoa viết đầu :
stlKeyword vs StlKeyword
Tiếp theo là dòng :

HiLink stlKeyword StlKeyword

Khi ta thêm dòng này thì thằng trong folder colors "delek.vim" mới bắt đầu có hiệu lực.
Save lại chúng ta sẽ có màu mà chúng ta đã chọn.
Bây giờ ta quay lại với file delek.vim một chúng để tìm hiểu làm sao thêm một màu mới cho nó :
Ta để ý dòng :

hi StlKeyword cterm=NONE ctermfg=NONE gui=bold guifg=#1E90FF

Ở đây ta không cần quan tâm thằng cterm và ctermfg, cái chúng ta cần chỉ là thằng gui và guifg mà thôi.
gui : là kiểu và có giá trị ( bold, italic, underline )
guifg : là các màu chúng ta định nghĩa, nó có thể ở dạng chữ hay ở dạng hexa deximal.
Những con số này thì chúng ta có thể tra cứu online hay sử dụng một text editor khác, vào trong phần chọn màu của nó và chọn. Ở đây mình dùng Codeblock để chọn màu.
Vậy là chúng ta xong, bây giờ hãy vào colorsheme duới tab "edit" và chọn lại colorsheme delek.vim và enjoy ^_^ !

No comments:

Post a Comment