diff --git a/README.md b/README.md
index 980a2c0..f910a9b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
 # TODO
 - 关键字高亮
 - 多风格样式
-- 移动光标自动关闭窗口
 - etc
+- ~~移动光标自动关闭窗口~~
 
 # FIXME
-- cursor模式下会自动聚焦在新窗口
+- ~~cursor模式下会自动聚焦在新窗口~~
diff --git a/install.sh b/install.sh
new file mode 100755
index 0000000..82e79d8
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+
+wget https://github.com/skywind3000/ECDICT-ultimate/releases/download/1.0.0/ecdict-ultimate-sqlite.zip -O /tmp/dict.zip
+
+unzip /tmp/dict.zip -d $HOME/.vim/dict
+
+rm -rf /tmp/dict.zip
diff --git a/lua/Trans/conf.lua b/lua/Trans/conf.lua
index 12ca060..6c81ceb 100644
--- a/lua/Trans/conf.lua
+++ b/lua/Trans/conf.lua
@@ -13,13 +13,21 @@ return {
         Trans_en = true,
         Trans_zh = true,
         wrap = true,
+        border_style = 'rounded',
+        view = 'cursor',
+        offset_x = 2,
+        offset_y = 2,
     },
-    view = {
-        -- TODO: style: buffer | cursor | window
-        -- style = 'buffer',
-        -- buffer_pos = 'bottom', -- only works when view.style == 'buffer'
+    order = {
+        'title',
+        'tag',
+        'pos',
+        'exchange',
+        'zh',
+        'en',
     },
-    db_path = '/home/zoran/project/neovim/ecdict-ultimate-sqlite/ultimate.db', -- FIXME: change the path
+
+    db_path = '$HOME/.vim/dict/ultimate.db', -- FIXME: change the path
 
     icon = {
         star = '⭐',
@@ -39,8 +47,8 @@ return {
     -- TODO: precise match or return closest match result
     -- precise_match = true,
 
-    -- TODO: leamma search
-    -- leamma = false,
+    -- TODO: lemma search
+    -- lemma = false,
 
     -- TODO: register word
 }
diff --git a/lua/Trans/display.lua b/lua/Trans/display.lua
index a880fc1..97eb3b1 100644
--- a/lua/Trans/display.lua
+++ b/lua/Trans/display.lua
@@ -1,73 +1,64 @@
--- local conf = require("Trans").conf
 local M = {}
 
 local display = require("Trans").conf.display
 local icon = require("Trans").conf.icon
+local order = require("Trans").conf.order
 
 
 local buf = vim.api.nvim_create_buf(false, true)
-vim.api.nvim_buf_set_option(buf, 'filetype', 'Trans')
 local win = 0
+vim.api.nvim_buf_set_option(buf, 'filetype', 'Trans')
 
 
--- {
---     audio = "",
---     bnc = 5222,
---     definition = "n. slang for sexual intercourse",
---     exchange = "d:fucked/p:fucked/i:fucking/3:fucks/s:fucks",
---     frq = 5040,
---     id = 1180286,
---     phonetic = "fʌk",
---     pos = "n:37/v:63",
---     sw = "fuck",
---     tag = "",
---     translation = "vt. 与...性交, 欺骗, 诅咒\nvi. 性交\nn. 性交, 些微, 杂种\ninterj. 他妈的, 混帐",
---     word = "fuck"
---  }
-
 local function show_win(width, height)
     win = vim.api.nvim_open_win(buf, false, {
         relative = 'cursor',
         title = 'Trans',
         title_pos = 'center',
         style = display.style,
-        row = 2, col = 2, width = width > display.max_width and display.max_width or width,
+        col = display.offset_x,
+        row = display.offset_y,
+        width = width > display.max_width and display.max_width or width,
         height = height > display.max_height and display.max_height or height,
-        border = 'rounded',
-        focusable = false,
+        border = display.border_style,
+        focusable = true,
     })
     vim.api.nvim_win_set_option(win, 'wrap', display.wrap)
 end
 
--- @return string array
-local function get_text(query_res)
-    local text = {
-        -- NOTE: word + phonetic + collins_star
-        string.format('%s    [%s]    ', query_res.word, query_res.phonetic) ..
-            (display.oxford and (query_res.oxford == 1 and icon.isOxford .. '    ' or icon.notOxford .. '    ') or '') ..
-            ((display.collins_star and query_res.collins) and string.rep(icon.star, query_res.collins) or '')
-    }
+-- NOTE: title
+local function get_title(text, query_res)
+    local title = string.format('%s    [%s]    ', query_res.word, query_res.phonetic) ..
+        (display.oxford and (query_res.oxford == 1 and icon.isOxford .. '    ' or icon.notOxford .. '    ') or '') ..
+        ((display.collins_star and query_res.collins) and string.rep(icon.star, query_res.collins) or '')
+    table.insert(text, title)
+end
 
-    -- NOTE: tag
-    if display.tag and query_res.tag:len() > 0 then
+-- NOTE: tag
+local function get_tag(text, query_res)
+    if #query_res.tag > 0 then
         local tag = query_res.tag:gsub('zk', '中考'):gsub('gk', '高考'):gsub('ky', '考研'):gsub('cet4', '四级'):
             gsub('cet6', '六级'):
             gsub('ielts', '雅思'):gsub('toefl', '托福'):gsub('gre', 'GRE')
         table.insert(text, '标签:')
         table.insert(text, '    ' .. tag)
     end
+end
 
-    -- NOTE: pos 词性
-    if display.pos and query_res.pos:len() > 0 then
+-- NOTE: pos 词性
+local function get_pos(text, query_res)
+    if #query_res.pos > 0 then
         table.insert(text, '词性:')
-        -- TODO: figure out pos sense
-        table.insert(text, '    ' .. query_res.pos)
+        for v in vim.gsplit(query_res.pos, [[/]]) do
+            table.insert(text, string.format('    %s', v .. '%'))
+        end
+        table.insert(text, '')
     end
-    table.insert(text, '')
+end
 
-    -- NOTE: exchange
-    if display.exchange and query_res.exchange:len() > 0 then
-        -- local list = vim.gsplit(query_res.exchange, [[\]])
+-- NOTE: exchange
+local function get_exchange(text, query_res)
+    if #query_res.exchange > 0 then
         table.insert(text, '词形变化:')
         local exchange_map = {
             p = '过去式',
@@ -83,32 +74,55 @@ local function get_text(query_res)
             table.insert(text, string.format('    %s:  %s', exchange_map[v:sub(1, 1)], v:sub(3)))
             -- FIXME: 中文字符与字母位宽不一致, 暂时无法对齐
         end
+        table.insert(text, '')
     end
-    table.insert(text, '')
-
-    -- NOTE: 中文翻译
-    if display.Trans_zh and query_res.translation:len() > 0 then
+end
 
+-- NOTE: 中文翻译
+local function get_zh(text, query_res)
+    if #query_res.translation > 0 then
         table.insert(text, '中文翻译:')
         for v in vim.gsplit(query_res.translation, '\n') do
-            -- table.insert(text, '    ' .. v)
             table.insert(text, '    ' .. v)
         end
+        table.insert(text, '')
     end
-    table.insert(text, '')
+end
 
-    -- NOTE: 英文翻译
+
+-- NOTE: 英文翻译
+local function get_en(text, query_res)
     if display.Trans_en and query_res.definition:len() > 0 then
         table.insert(text, '英文翻译:')
         for v in vim.gsplit(query_res.definition, '\n') do
             table.insert(text, '    ' .. v)
         end
+        table.insert(text, '')
     end
-    table.insert(text, '')
+end
 
+
+local handler = {
+    title = get_title,
+    tag = get_tag,
+    pos = get_pos,
+    exchange = get_exchange,
+    zh = get_zh,
+    en = get_en,
+}
+
+
+-- @return string array
+local function get_text(query_res)
+    local text = {}
+    for _, v in pairs(order) do
+        handler[v](text, query_res)
+    end
     return text
 end
 
+
+
 local function set_text(query_res)
     local text = query_res and get_text(query_res) or { '没有找到相关定义' }
 
@@ -126,9 +140,6 @@ function M.query_cursor()
     vim.api.nvim_buf_set_option(buf, 'modifiable', true)
     local word = vim.fn.expand('<cword>')
     local res = require("Trans.database").query(word)
-
-    -- vim.pretty_print(res)
-
     local width, height = set_text(res)
     show_win(width, height)
     vim.api.nvim_buf_set_option(buf, 'modifiable', false)
@@ -144,7 +155,7 @@ end
 
 function M.close_win()
     if win > 0 then
-       vim.api.nvim_win_close(win, true) 
+        vim.api.nvim_win_close(win, true)
         win = 0
     end
 end
diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua
index 2becf6d..0338c4f 100644
--- a/lua/Trans/init.lua
+++ b/lua/Trans/init.lua
@@ -9,6 +9,14 @@ local M = {}
 
 M.conf = require("Trans.conf")
 function M.setup(conf)
+    if conf.display then
+        conf.display = vim.tbl_extend('force', M.conf.display, conf.display)
+    end
+
+    if conf.icon then
+        conf.icon = vim.tbl_extend('force', M.conf.icon, conf.icon)
+    end
+
     M.conf = vim.tbl_extend('force', M.conf, conf)
     require("Trans.setup")
 end