diff --git a/autoload/SpaceVim/layers/chat.vim b/autoload/SpaceVim/layers/chat.vim index 439d37054..8b75fc60a 100644 --- a/autoload/SpaceVim/layers/chat.vim +++ b/autoload/SpaceVim/layers/chat.vim @@ -53,7 +53,7 @@ function! SpaceVim#layers#chat#config() abort let g:chatting_server_ip = s:chat_address let g:chatting_server_port = s:chat_port let g:chatting_server_lib = s:chat_client_jar - call SpaceVim#mapping#space#def('nnoremap', ['a', 'h'], 'call chat#chatting#OpenMsgWin()', 'open-chat-window', 1) + call SpaceVim#mapping#space#def('nnoremap', ['a', 'h'], 'call chat#OpenMsgWin()', 'open-chat-window', 1) endfunction function! SpaceVim#layers#chat#health() abort diff --git a/bundle/Chatting-server/src/main/java/com/wsdjeg/chat/server/Command.java b/bundle/Chatting-server/src/main/java/com/wsdjeg/chat/server/Command.java index 3c8bfa52a..383d1fa7b 100644 --- a/bundle/Chatting-server/src/main/java/com/wsdjeg/chat/server/Command.java +++ b/bundle/Chatting-server/src/main/java/com/wsdjeg/chat/server/Command.java @@ -15,7 +15,7 @@ public class Command { cmds.put("/help" , " /help : show help message."); cmds.put("/login" , " /login USERNAME PASSWORD : login with your chatting account."); cmds.put("/logout" , " /logout : logout current account."); - cmds.put("/signup" , " /signup : create a new account."); + cmds.put("/signup" , " /signup USERNAME PASSWORD PASSWORD: create a new account."); cmds.put("/password" , " /password : change the password of current user."); cmds.put("/names" , " /names : list all the user in current channel."); cmds.put("/join" , " /join : join a channel."); diff --git a/bundle/vim-chat/README.md b/bundle/vim-chat/README.md index ab61395b5..44256df1e 100644 --- a/bundle/vim-chat/README.md +++ b/bundle/vim-chat/README.md @@ -1,31 +1,3 @@ ## vim-chat -chat in neovim and vim8 - - -### Install - -```viml -call dein#add('wsdjeg/vim-chat') -``` - -now you can chatting with me by `call chat#chatting#OpenMsgWin()`, insert `/help` for help message; - -### 微信及QQ聊天 - -#### 依赖 - -- [mojo-webqq](https://github.com/sjdy521/Mojo-Webqq) 和 [mojo-weixin](https://github.com/sjdy521/Mojo-Weixin):用于将QQ及微信协议转换成irc协议 -- IRC 依赖模块: `cpanm -v Mojo::IRC::Server::Chinese`, 详见: [irc.md](https://github.com/sjdy521/Mojo-Webqq/blob/master/IRC.md) -- [irssi](https://irssi.org/): irc 聊天客户端 -- [feh](https://feh.finalrewind.org/): 图片查看器,用于打开二维码 -- [neovim](https://github.com/neovim/neovim): vim8 的异步存在[问题](https://github.com/vim/vim/issues/1198),无法实现相应功能,故只能在neovim下使用 -- Linux: 目前仅在Linux下测试成功, Windows 下请直接使用QQ客户端 - -#### 启动 - -首先启动 QQ 服务器 `call chat#qq#start()`, 然后会自动弹出一个二维码,手机扫描下就可以登录了。neovim 默认使用 `Alt + x` 打开/关闭聊天窗口。 - -#### 效果图 - -![Markdown](http://i2.kiimg.com/1949/c18404d7afdc7f3a.gif) +The chatting client for vim and neovim. diff --git a/bundle/vim-chat/autoload/chat.vim b/bundle/vim-chat/autoload/chat.vim index ada260a59..fd4a8434a 100644 --- a/bundle/vim-chat/autoload/chat.vim +++ b/bundle/vim-chat/autoload/chat.vim @@ -1,13 +1,502 @@ -function! chat#startServer(name) abort +"============================================================================= +" chatting.vim --- chatting client +" Copyright (c) 2016-2019 Wang Shidong & Contributors +" Author: Wang Shidong < wsdjeg@outlook.com > +" URL: https://spacevim.org +" License: GPLv3 +"============================================================================= -endfunction -function! chat#openWin(...) abort - if a:0 == 0 - call chat#chatting#OpenMsgWin() - else - if !empty(globpath(&rtp,'autoload/chat/' . a:1 .'.vim')) - call call('chat#' . a:1 . '#OpenMsgWin', []) - endif +scriptencoding utf-8 +let s:server_lib = get(g:, 'chatting_server_lib', '~/jars/Chatting-1.0-SNAPSHOT.jar') +let s:login_user = '' +let s:server_job_id = 0 +let s:client_job_id = 0 +let s:debug_log = [] +let s:chatting_commands = [] +let s:current_channel = '' +let s:last_channel = '' +let s:server_ip = get(g:, 'chatting_server_ip', '127.0.0.1') +let s:server_port = get(g:, 'chatting_server_port', 8080) +let s:server_database = get(g:, 'chatting_server_database', '~/Desktop/database.txt') +let s:vim8_ch_waittime = get(g:, 'chatting_ch_waittime', 100) +let s:close_windows_char = get(g:, 'chatting_close_win_char',"\") +let s:messages = [] +let s:opened_channels = [] +let s:unread_msg_num = {} +let s:st_sep = '' + +let s:JOB = SpaceVim#api#import('job') + +function! s:push_message(msg) abort + if type(a:msg) == type([]) + for m in a:msg + if !empty(m) + call s:hander_msg(m) + endif + endfor + else + if !empty(a:msg) + call s:hander_msg(a:msg) endif + endif endfunction + +function! s:hander_msg(msg) abort + let info = json_decode(a:msg) + call add(s:messages, info) + if info['type'] ==# 'onWindowChange' + let s:current_channel = info['name'] + if index(s:opened_channels, s:current_channel) == -1 + call add(s:opened_channels, s:current_channel) + endif + if s:current_channel !=# '' + call s:update_statusline() + endif + elseif info['type'] ==# 'group_message' + let n = get(s:unread_msg_num, info['group_name'], 0) + let n += 1 + if has_key(s:unread_msg_num, info['group_name']) + call remove(s:unread_msg_num, info['group_name']) + endif + call extend(s:unread_msg_num, {info['group_name'] : n}) + if s:current_channel !=# '' + call s:update_statusline() + endif + elseif info['type'] ==# 'info_message' + if info['context'] =~# 'you are logined as ' + let s:login_user = substitute(info['context'], 'you are logined as ', '', 'g') + endif + elseif info['type'] ==# 'onGetConnection' + " /quit is usegd to close chatting windows + let s:chatting_commands = split(info['commands'], ',') + ['/quit'] + endif + +endfunction + +function! chat#start() abort + if s:server_job_id == 0 + call chat#logger#info('startting server, server_lib is ' . s:server_lib . '(' . (filereadable(s:server_lib) ? 'no such file' : 'file exists' ). ')') + let s:server_job_id = s:JOB.start([ + \ 'java', + \ '-cp', s:server_lib, 'com.wsdjeg.chat.Server', + \ '-D', s:server_port, + \ '--database', s:server_database, + \ ],{ + \ 'on_stdout' : function('s:server_handler'), + \ 'on_exit' : function('s:server_exit'), + \ }) + endif +endfunction + +function! s:server_handler(id, data, event) abort + for data in a:data + call chat#logger#info('server stdout:' . data) + endfor +endfunction + +function! s:server_exit(id, data, event) abort + call chat#logger#info('server exit with code:' . a:data) +endfunction + +function! s:client_handler(id, data, event) abort + if a:event ==# 'stdout' + call s:push_message(a:data) + call s:update_msg_screen() + elseif a:event ==# 'exit' + call chat#logger#info('client exit with code:' . a:data) + let s:client_job_id = 0 + endif +endfunction + +function! s:ch_callbakc(ch, msg) abort + call s:push_message(a:msg) + call s:update_msg_screen() +endfunction + +function! s:start_client() abort + if has('nvim') + if s:client_job_id == 0 + let s:client_job_id = jobstart(['java', '-cp', s:server_lib, 'com.wsdjeg.chat.Client', s:server_ip, s:server_port],{ + \ 'on_stdout' : function('s:client_handler'), + \ 'on_exit' : function('s:client_handler') + \ }) + call chat#logger#info('Server_lib:' . s:server_lib) + endif + else + let s:channel = ch_open(s:server_ip . ':' . s:server_port, + \ {'callback': function('s:ch_callbakc') ,'mode': 'nl', 'waittime': s:vim8_ch_waittime}) + call chat#logger#info('Client channel status:' . ch_status(s:channel)) + endif + call chat#logger#info('Client startting with server ip(' . s:server_ip . ') port(' . s:server_port . ')') +endfunction + +let s:name = '__Chatting__' +let s:c_base = '>>> ' +let s:c_begin = '' +let s:c_char = '' +let s:c_end = '' +let s:msg_win_opened = 0 +function! chat#OpenMsgWin() abort + if has('nvim') + if s:client_job_id == 0 + call s:start_client() + endif + else + if !exists('s:channel') || ch_status(s:channel) !=# 'open' + call s:start_client() + endif + endif + if bufwinnr(s:name) < 0 + if bufnr(s:name) != -1 + exe 'silent! botright split ' . '+b' . bufnr(s:name) + else + exe 'silent! botright split ' . s:name + endif + else + exec bufwinnr(s:name) . 'wincmd w' + endif + call s:windowsinit() + call s:init_hi() + setl modifiable + let s:msg_win_opened = 1 + if !empty(s:last_channel) + let s:current_channel = s:last_channel + endif + call s:update_msg_screen() + call s:update_statusline() + call s:echon() + while get(s:, 'quit_chating_win', 0) == 0 + let nr = getchar() + if nr !=# "\" && nr !=# "\" + let s:complete_input_history_num = [0,0] + endif + if nr != 9 + let s:complete_num = 0 + endif + if nr == 13 + call s:enter() + elseif nr ==# "\" || nr == 6 " 向右移动光标 + let s:c_begin = s:c_begin . s:c_char + let s:c_char = matchstr(s:c_end, '^.') + let s:c_end = substitute(s:c_end, '^.', '', 'g') + elseif nr == 21 " ctrl+u clean the message + let s:c_begin = '' + elseif nr == 9 " use complete str + if s:complete_num == 0 + let complete_base = s:c_begin + else + let s:c_begin = complete_base + endif + let s:c_begin = s:complete(complete_base, s:complete_num) + let s:complete_num += 1 + elseif nr == 11 " ctrl+k delete the chars from cursor to the end + let s:c_char = '' + let s:c_end = '' + elseif nr ==# "\" || nr ==# "\" + "+ 移动到左边一个聊天窗口 + call s:previous_channel() + elseif nr ==# "\" || nr ==# "\" + "+ 移动到右边一个聊天窗口 + call s:next_channel() + elseif nr ==# "\" || nr == 2 " 向左移动光标 + if s:c_begin !=# '' + let s:c_end = s:c_char . s:c_end + let s:c_char = matchstr(s:c_begin, '.$') + let s:c_begin = substitute(s:c_begin, '.$', '', 'g') + endif + elseif nr ==# "\" + let l = line('.') - winheight('$') + if l < 0 + exe 0 + else + exe l + endif + elseif nr ==# "\" + exe line('.') + winheight('$') + elseif nr ==# "\" || nr == 1 " + a 将光标移动到行首 + let s:c_end = substitute(s:c_begin . s:c_char . s:c_end, '^.', '', 'g') + let s:c_char = matchstr(s:c_begin, '^.') + let s:c_begin = '' + elseif nr ==# "\" || nr == 5 " + e 将光标移动到行末 + let s:c_begin = s:c_begin . s:c_char . s:c_end + let s:c_char = '' + let s:c_end = '' + elseif nr ==# s:close_windows_char || nr ==# char2nr(s:close_windows_char) + let s:quit_chating_win = 1 + elseif nr == 8 || nr ==# "\" " ctrl+h or delete last char + let s:c_begin = substitute(s:c_begin,'.$','','g') + elseif nr ==# "\" + if s:complete_input_history_num == [0,0] + let complete_input_history_base = s:c_begin + let s:c_char = '' + let s:c_end = '' + else + let s:c_begin = complete_input_history_base + endif + let s:complete_input_history_num[0] += 1 + let s:c_begin = s:complete_input_history(complete_input_history_base, s:complete_input_history_num) + elseif nr ==# "\" + if s:complete_input_history_num == [0,0] + let complete_input_history_base = s:c_begin + let s:c_char = '' + let s:c_end = '' + else + let s:c_begin = complete_input_history_base + endif + let s:complete_input_history_num[1] += 1 + let s:c_begin = s:complete_input_history(complete_input_history_base, s:complete_input_history_num) + else + let s:c_begin .= nr2char(nr) + endif + call s:echon() + endwhile + setl nomodifiable + exe 'bd ' . bufnr(s:name) + let s:quit_chating_win = 0 + let s:last_channel = s:current_channel + let s:current_channel = '' + let s:msg_win_opened = 0 + normal! : +endfunction + +function! s:update_msg_screen() abort + if s:msg_win_opened + normal! ggdG + for msg in s:messages + if msg['type'] ==# 'group_message' && msg['group_name'] ==# s:current_channel + call append(line('$'), '[' . msg['time'] . '] < ' . msg['sendder'] . ' > ' . msg['context']) + elseif msg['type'] ==# 'info_message' && msg['context'] !~# '^join channel :' + call append(line('$'), '[' . msg['time'] . '] ' . msg['context']) + elseif msg['type'] ==# 'user_message' + \ && ( + \ msg['sendder'] ==# s:current_channel + \ || + \ (msg['sendder'] ==# s:login_user && msg['receiver'] ==# s:current_channel) + \ ) + call append(line('$'), '[' . msg['time'] . '] < ' . msg['sendder'] . ' > ' . msg['context']) + endif + endfor + normal! gg + delete + normal! G + redraw + call s:echon() + endif +endfunction + +function! s:echon() abort + redraw! + echohl Comment | echon s:c_base + echohl None | echon s:c_begin + echohl Wildmenu | echon s:c_char + echohl None | echon s:c_end +endfunction + +fu! s:windowsinit() abort + " option + setl fileformat=unix + setl fileencoding=utf-8 + setl iskeyword=@,48-57,_ + setl noreadonly + setl buftype=nofile + setl bufhidden=wipe + setl noswapfile + setl nobuflisted + setl nolist + setl nonumber + setl norelativenumber + setl wrap + setl winfixwidth + setl winfixheight + setl textwidth=0 + setl nospell + setl nofoldenable + setl cursorline + setl filetype=vimchat +endf + +function! s:debug() abort + tabnew + for line in s:debug_log + call append(line('$'), line) + endfor + nnoremap q :bd! +endfunction + + +let s:enter_history = [] +function! s:enter() abort + if s:c_begin . s:c_char . s:c_end =~# '/quit\s*' + let s:quit_chating_win = 1 + let s:c_end = '' + let s:c_char = '' + let s:c_begin = '' + return + endif + if has('nvim') + if s:client_job_id != 0 + call jobsend(s:client_job_id, [s:c_begin . s:c_char . s:c_end, '']) + endif + else + call ch_sendraw(s:channel, s:c_begin . s:c_char . s:c_end ."\n") + endif + call add(s:enter_history, s:c_begin . s:c_char . s:c_end) + let s:c_end = '' + let s:c_char = '' + let s:c_begin = '' +endfunction + +let s:complete_num = 0 +function! s:complete(base,num) abort + if a:base =~# '^/[a-z]*$' + let rsl = filter(copy(s:chatting_commands), "v:val =~# a:base .'[^\ .]*'") + if len(rsl) > 0 + return rsl[a:num % len(rsl)] . ' ' + endif + endif + + return a:base + +endfunction +let s:complete_input_history_num = [0,0] +function! s:complete_input_history(base,num) abort + let results = filter(copy(s:enter_history), "v:val =~# '^' . a:base") + if len(results) > 0 + call add(results, a:base) + let index = ((len(results) - 1) - a:num[0] + a:num[1]) % len(results) + return results[index] + else + return a:base + endif +endfunction + +function! s:init_hi() abort + if get(s:, 'init_hi_done', 0) == 0 + " current channel + hi! ChattingHI1 ctermbg=003 ctermfg=Black guibg=#fabd2f guifg=#282828 + " channel with new msg + hi! ChattingHI2 ctermbg=005 ctermfg=Black guibg=#b16286 guifg=#282828 + " normal channel + hi! ChattingHI3 ctermbg=007 ctermfg=Black guibg=#8ec07c guifg=#282828 + " end + hi! ChattingHI4 ctermbg=243 guibg=#7c6f64 + " current channel + end + hi! ChattingHI5 guibg=#7c6f64 guifg=#fabd2f + " current channel + new msg channel + hi! ChattingHI6 guibg=#b16286 guifg=#fabd2f + " current channel + normal channel + hi! ChattingHI7 guibg=#8ec07c guifg=#fabd2f + " new msg channel + end + hi! ChattingHI8 guibg=#7c6f64 guifg=#b16286 + " new msg channel + current channel + hi! ChattingHI9 guibg=#fabd2f guifg=#b16286 + " new msg channel + normal channel + hi! ChattingHI10 guibg=#8ec07c guifg=#b16286 + " new msg channel + new msg channel + hi! ChattingHI11 guibg=#b16286 guifg=#b16286 + " normal channel + end + hi! ChattingHI12 guibg=#7c6f64 guifg=#8ec07c + " normal channel + normal channel + hi! ChattingHI13 guibg=#8ec07c guifg=#8ec07c + " normal channel + new msg channel + hi! ChattingHI14 guibg=#b16286 guifg=#8ec07c + " normal channel + current channel + hi! ChattingHI15 guibg=#fabd2f guifg=#8ec07c + let s:init_hi_done = 1 + endif +endfunction +function! s:update_statusline() abort + let st = '' + for ch in s:opened_channels + let ch = substitute(ch, ' ', '\ ', 'g') + if ch == s:current_channel + if has_key(s:unread_msg_num, s:current_channel) + call remove(s:unread_msg_num, s:current_channel) + endif + let st .= '%#ChattingHI1#[' . ch . ']' + if index(s:opened_channels, ch) == len(s:opened_channels) - 1 + let st .= '%#ChattingHI5#' . s:st_sep + elseif get(s:unread_msg_num, s:opened_channels[index(s:opened_channels, ch) + 1], 0) > 0 + let st .= '%#ChattingHI6#' . s:st_sep + else + let st .= '%#ChattingHI7#' . s:st_sep + endif + else + let n = get(s:unread_msg_num, ch, 0) + if n > 0 + let st .= '%#ChattingHI2#[' . ch . '(' . n . 'new)]' + if index(s:opened_channels, ch) == len(s:opened_channels) - 1 + let st .= '%#ChattingHI8#' . s:st_sep + elseif get(s:unread_msg_num, s:opened_channels[index(s:opened_channels, ch) + 1], 0) > 0 + \ && s:opened_channels[index(s:opened_channels, ch) + 1] !=# s:current_channel + let st .= '%#ChattingHI11#' . s:st_sep + elseif s:opened_channels[index(s:opened_channels, ch) + 1] ==# s:current_channel + let st .= '%#ChattingHI9#' . s:st_sep + else + let st .= '%#ChattingHI10#' . s:st_sep + endif + else + let st .= '%#ChattingHI3#[' . ch . ']' + if index(s:opened_channels, ch) == len(s:opened_channels) - 1 + let st .= '%#ChattingHI12#' . s:st_sep + elseif get(s:unread_msg_num, s:opened_channels[index(s:opened_channels, ch) + 1], 0) > 0 + \ && s:opened_channels[index(s:opened_channels, ch) + 1] !=# s:current_channel + let st .= '%#ChattingHI14#' . s:st_sep + elseif s:opened_channels[index(s:opened_channels, ch) + 1] ==# s:current_channel + let st .= '%#ChattingHI15#' . s:st_sep + else + let st .= '%#ChattingHI13#' . s:st_sep + endif + endif + endif + endfor + let st .= '%#ChattingHI4# ' + exe 'set statusline=' . st +endfunction + +function! s:previous_channel() abort + let id = index(s:opened_channels, s:current_channel) + let id -= 1 + if id < 0 + let id = id + len(s:opened_channels) + endif + let s:current_channel = s:opened_channels[id] + if s:current_channel =~# '^#' + call s:send('/join ' . s:current_channel) + else + call s:send('/query ' . s:current_channel) + endif + call s:update_msg_screen() + call s:update_statusline() +endfunction + +function! s:next_channel() abort + let id = index(s:opened_channels, s:current_channel) + let id += 1 + if id > len(s:opened_channels) - 1 + let id = id - len(s:opened_channels) + endif + let s:current_channel = s:opened_channels[id] + if s:current_channel =~# '^#' + call s:send('/join ' . s:current_channel) + else + call s:send('/query ' . s:current_channel) + endif + call s:update_msg_screen() + call s:update_statusline() + +endfunction + +function! s:send(msg) abort + if has('nvim') + if s:client_job_id != 0 + call jobsend(s:client_job_id, [a:msg, '']) + endif + else + call ch_sendraw(s:channel, a:msg ."\n") + endif +endfunction + +call chat#debug#defind('chatting', function('s:debug')) + diff --git a/bundle/vim-chat/autoload/chat/chatting.vim b/bundle/vim-chat/autoload/chat/chatting.vim deleted file mode 100644 index b00127035..000000000 --- a/bundle/vim-chat/autoload/chat/chatting.vim +++ /dev/null @@ -1,492 +0,0 @@ -scriptencoding utf-8 -let s:server_lib = get(g:, 'chatting_server_lib', '~/jars/Chatting-1.0-SNAPSHOT.jar') -let s:login_user = '' -let s:server_job_id = 0 -let s:client_job_id = 0 -let s:debug_log = [] -let s:chatting_commands = [] -let s:current_channel = '' -let s:last_channel = '' -let s:server_ip = get(g:, 'chatting_server_ip', '127.0.0.1') -let s:server_port = get(g:, 'chatting_server_port', 8080) -let s:server_database = get(g:, 'chatting_server_database', '~/Desktop/database.txt') -let s:vim8_ch_waittime = get(g:, 'chatting_ch_waittime', 100) -let s:close_windows_char = get(g:, 'chatting_close_win_char',"\") -let s:messages = [] -let s:opened_channels = [] -let s:unread_msg_num = {} -let s:st_sep = '' - -let s:JOB = SpaceVim#api#import('job') - -function! s:push_message(msg) abort - if type(a:msg) == type([]) - for m in a:msg - if !empty(m) - call s:hander_msg(m) - endif - endfor - else - if !empty(a:msg) - call s:hander_msg(a:msg) - endif - endif -endfunction - -function! s:hander_msg(msg) abort - let info = json_decode(a:msg) - call add(s:messages, info) - if info['type'] ==# 'onWindowChange' - let s:current_channel = info['name'] - if index(s:opened_channels, s:current_channel) == -1 - call add(s:opened_channels, s:current_channel) - endif - if s:current_channel !=# '' - call s:update_statusline() - endif - elseif info['type'] ==# 'group_message' - let n = get(s:unread_msg_num, info['group_name'], 0) - let n += 1 - if has_key(s:unread_msg_num, info['group_name']) - call remove(s:unread_msg_num, info['group_name']) - endif - call extend(s:unread_msg_num, {info['group_name'] : n}) - if s:current_channel !=# '' - call s:update_statusline() - endif - elseif info['type'] ==# 'info_message' - if info['context'] =~# 'you are logined as ' - let s:login_user = substitute(info['context'], 'you are logined as ', '', 'g') - endif - elseif info['type'] ==# 'onGetConnection' - let s:chatting_commands = split(info['commands'], ',') - endif - -endfunction - -function! chat#chatting#start() abort - if s:server_job_id == 0 - call chat#logger#info('startting server, server_lib is ' . s:server_lib . '(' . (filereadable(s:server_lib) ? 'no such file' : 'file exists' ). ')') - let s:server_job_id = s:JOB.start([ - \ 'java', - \ '-cp', s:server_lib, 'com.wsdjeg.chat.Server', - \ '-D', s:server_port, - \ '--database', s:server_database, - \ ],{ - \ 'on_stdout' : function('s:server_handler'), - \ 'on_exit' : function('s:server_exit'), - \ }) - endif -endfunction - -function! s:server_handler(id, data, event) abort - for data in a:data - call chat#logger#info('server stdout:' . data) - endfor -endfunction - -function! s:server_exit(id, data, event) abort - call chat#logger#info('server exit with code:' . a:data) -endfunction - -function! s:client_handler(id, data, event) abort - if a:event ==# 'stdout' - call s:push_message(a:data) - call s:update_msg_screen() - elseif a:event ==# 'exit' - call chat#logger#info('client exit with code:' . a:data) - let s:client_job_id = 0 - endif -endfunction - -function! s:ch_callbakc(ch, msg) abort - call s:push_message(a:msg) - call s:update_msg_screen() -endfunction - -function! s:start_client() abort - if has('nvim') - if s:client_job_id == 0 - let s:client_job_id = jobstart(['java', '-cp', s:server_lib, 'com.wsdjeg.chat.Client', s:server_ip, s:server_port],{ - \ 'on_stdout' : function('s:client_handler'), - \ 'on_exit' : function('s:client_handler') - \ }) - call chat#logger#info('Server_lib:' . s:server_lib) - endif - else - let s:channel = ch_open(s:server_ip . ':' . s:server_port, - \ {'callback': function('s:ch_callbakc') ,'mode': 'nl', 'waittime': s:vim8_ch_waittime}) - call chat#logger#info('Client channel status:' . ch_status(s:channel)) - endif - call chat#logger#info('Client startting with server ip(' . s:server_ip . ') port(' . s:server_port . ')') -endfunction - -let s:name = '__Chatting__' -let s:c_base = '>>> ' -let s:c_begin = '' -let s:c_char = '' -let s:c_end = '' -let s:msg_win_opened = 0 -function! chat#chatting#OpenMsgWin() abort - if has('nvim') - if s:client_job_id == 0 - call s:start_client() - endif - else - if !exists('s:channel') || ch_status(s:channel) !=# 'open' - call s:start_client() - endif - endif - if bufwinnr(s:name) < 0 - if bufnr(s:name) != -1 - exe 'silent! botright split ' . '+b' . bufnr(s:name) - else - exe 'silent! botright split ' . s:name - endif - else - exec bufwinnr(s:name) . 'wincmd w' - endif - call s:windowsinit() - call s:init_hi() - setl modifiable - let s:msg_win_opened = 1 - if !empty(s:last_channel) - let s:current_channel = s:last_channel - endif - call s:update_msg_screen() - call s:update_statusline() - call s:echon() - while get(s:, 'quit_chating_win', 0) == 0 - let nr = getchar() - if nr !=# "\" && nr !=# "\" - let s:complete_input_history_num = [0,0] - endif - if nr != 9 - let s:complete_num = 0 - endif - if nr == 13 - call s:enter() - elseif nr ==# "\" || nr == 6 " 向右移动光标 - let s:c_begin = s:c_begin . s:c_char - let s:c_char = matchstr(s:c_end, '^.') - let s:c_end = substitute(s:c_end, '^.', '', 'g') - elseif nr == 21 " ctrl+u clean the message - let s:c_begin = '' - elseif nr == 9 " use complete str - if s:complete_num == 0 - let complete_base = s:c_begin - else - let s:c_begin = complete_base - endif - let s:c_begin = s:complete(complete_base, s:complete_num) - let s:complete_num += 1 - elseif nr == 11 " ctrl+k delete the chars from cursor to the end - let s:c_char = '' - let s:c_end = '' - elseif nr ==# "\" || nr ==# "\" - "+ 移动到左边一个聊天窗口 - call s:previous_channel() - elseif nr ==# "\" || nr ==# "\" - "+ 移动到右边一个聊天窗口 - call s:next_channel() - elseif nr ==# "\" || nr == 2 " 向左移动光标 - if s:c_begin !=# '' - let s:c_end = s:c_char . s:c_end - let s:c_char = matchstr(s:c_begin, '.$') - let s:c_begin = substitute(s:c_begin, '.$', '', 'g') - endif - elseif nr ==# "\" - let l = line('.') - winheight('$') - if l < 0 - exe 0 - else - exe l - endif - elseif nr ==# "\" - exe line('.') + winheight('$') - elseif nr ==# "\" || nr == 1 " + a 将光标移动到行首 - let s:c_end = substitute(s:c_begin . s:c_char . s:c_end, '^.', '', 'g') - let s:c_char = matchstr(s:c_begin, '^.') - let s:c_begin = '' - elseif nr ==# "\" || nr == 5 " + e 将光标移动到行末 - let s:c_begin = s:c_begin . s:c_char . s:c_end - let s:c_char = '' - let s:c_end = '' - elseif nr ==# s:close_windows_char || nr ==# char2nr(s:close_windows_char) - let s:quit_chating_win = 1 - elseif nr == 8 || nr ==# "\" " ctrl+h or delete last char - let s:c_begin = substitute(s:c_begin,'.$','','g') - elseif nr ==# "\" - if s:complete_input_history_num == [0,0] - let complete_input_history_base = s:c_begin - let s:c_char = '' - let s:c_end = '' - else - let s:c_begin = complete_input_history_base - endif - let s:complete_input_history_num[0] += 1 - let s:c_begin = s:complete_input_history(complete_input_history_base, s:complete_input_history_num) - elseif nr ==# "\" - if s:complete_input_history_num == [0,0] - let complete_input_history_base = s:c_begin - let s:c_char = '' - let s:c_end = '' - else - let s:c_begin = complete_input_history_base - endif - let s:complete_input_history_num[1] += 1 - let s:c_begin = s:complete_input_history(complete_input_history_base, s:complete_input_history_num) - else - let s:c_begin .= nr2char(nr) - endif - call s:echon() - endwhile - setl nomodifiable - exe 'bd ' . bufnr(s:name) - let s:quit_chating_win = 0 - let s:last_channel = s:current_channel - let s:current_channel = '' - let s:msg_win_opened = 0 - normal! : -endfunction - -function! s:update_msg_screen() abort - if s:msg_win_opened - normal! ggdG - for msg in s:messages - if msg['type'] ==# 'group_message' && msg['group_name'] ==# s:current_channel - call append(line('$'), '[' . msg['time'] . '] < ' . msg['sendder'] . ' > ' . msg['context']) - elseif msg['type'] ==# 'info_message' && msg['context'] !~# '^join channel :' - call append(line('$'), '[' . msg['time'] . '] ' . msg['context']) - elseif msg['type'] ==# 'user_message' - \ && ( - \ msg['sendder'] ==# s:current_channel - \ || - \ (msg['sendder'] ==# s:login_user && msg['receiver'] ==# s:current_channel) - \ ) - call append(line('$'), '[' . msg['time'] . '] < ' . msg['sendder'] . ' > ' . msg['context']) - endif - endfor - normal! gg - delete - normal! G - redraw - call s:echon() - endif -endfunction - -function! s:echon() abort - redraw! - echohl Comment | echon s:c_base - echohl None | echon s:c_begin - echohl Wildmenu | echon s:c_char - echohl None | echon s:c_end -endfunction - -fu! s:windowsinit() abort - " option - setl fileformat=unix - setl fileencoding=utf-8 - setl iskeyword=@,48-57,_ - setl noreadonly - setl buftype=nofile - setl bufhidden=wipe - setl noswapfile - setl nobuflisted - setl nolist - setl nonumber - setl norelativenumber - setl wrap - setl winfixwidth - setl winfixheight - setl textwidth=0 - setl nospell - setl nofoldenable - setl cursorline - setl filetype=vimchat -endf - -function! s:debug() abort - tabnew - for line in s:debug_log - call append(line('$'), line) - endfor - nnoremap q :bd! -endfunction - - -let s:enter_history = [] -function! s:enter() abort - if s:c_begin . s:c_char . s:c_end ==# '/quit' - let s:quit_chating_win = 1 - let s:c_end = '' - let s:c_char = '' - let s:c_begin = '' - return - endif - if has('nvim') - if s:client_job_id != 0 - call jobsend(s:client_job_id, [s:c_begin . s:c_char . s:c_end, '']) - endif - else - call ch_sendraw(s:channel, s:c_begin . s:c_char . s:c_end ."\n") - endif - call add(s:enter_history, s:c_begin . s:c_char . s:c_end) - let s:c_end = '' - let s:c_char = '' - let s:c_begin = '' -endfunction - -let s:complete_num = 0 -function! s:complete(base,num) abort - if a:base =~# '^/[a-z]*$' - let rsl = filter(copy(s:chatting_commands), "v:val =~# a:base .'[^\ .]*'") - if len(rsl) > 0 - return rsl[a:num % len(rsl)] . ' ' - endif - endif - - return a:base - -endfunction -let s:complete_input_history_num = [0,0] -function! s:complete_input_history(base,num) abort - let results = filter(copy(s:enter_history), "v:val =~# '^' . a:base") - if len(results) > 0 - call add(results, a:base) - let index = ((len(results) - 1) - a:num[0] + a:num[1]) % len(results) - return results[index] - else - return a:base - endif -endfunction - -function! s:init_hi() abort - if get(s:, 'init_hi_done', 0) == 0 - " current channel - hi! ChattingHI1 ctermbg=003 ctermfg=Black guibg=#fabd2f guifg=#282828 - " channel with new msg - hi! ChattingHI2 ctermbg=005 ctermfg=Black guibg=#b16286 guifg=#282828 - " normal channel - hi! ChattingHI3 ctermbg=007 ctermfg=Black guibg=#8ec07c guifg=#282828 - " end - hi! ChattingHI4 ctermbg=243 guibg=#7c6f64 - " current channel + end - hi! ChattingHI5 guibg=#7c6f64 guifg=#fabd2f - " current channel + new msg channel - hi! ChattingHI6 guibg=#b16286 guifg=#fabd2f - " current channel + normal channel - hi! ChattingHI7 guibg=#8ec07c guifg=#fabd2f - " new msg channel + end - hi! ChattingHI8 guibg=#7c6f64 guifg=#b16286 - " new msg channel + current channel - hi! ChattingHI9 guibg=#fabd2f guifg=#b16286 - " new msg channel + normal channel - hi! ChattingHI10 guibg=#8ec07c guifg=#b16286 - " new msg channel + new msg channel - hi! ChattingHI11 guibg=#b16286 guifg=#b16286 - " normal channel + end - hi! ChattingHI12 guibg=#7c6f64 guifg=#8ec07c - " normal channel + normal channel - hi! ChattingHI13 guibg=#8ec07c guifg=#8ec07c - " normal channel + new msg channel - hi! ChattingHI14 guibg=#b16286 guifg=#8ec07c - " normal channel + current channel - hi! ChattingHI15 guibg=#fabd2f guifg=#8ec07c - let s:init_hi_done = 1 - endif -endfunction -function! s:update_statusline() abort - let st = '' - for ch in s:opened_channels - let ch = substitute(ch, ' ', '\ ', 'g') - if ch == s:current_channel - if has_key(s:unread_msg_num, s:current_channel) - call remove(s:unread_msg_num, s:current_channel) - endif - let st .= '%#ChattingHI1#[' . ch . ']' - if index(s:opened_channels, ch) == len(s:opened_channels) - 1 - let st .= '%#ChattingHI5#' . s:st_sep - elseif get(s:unread_msg_num, s:opened_channels[index(s:opened_channels, ch) + 1], 0) > 0 - let st .= '%#ChattingHI6#' . s:st_sep - else - let st .= '%#ChattingHI7#' . s:st_sep - endif - else - let n = get(s:unread_msg_num, ch, 0) - if n > 0 - let st .= '%#ChattingHI2#[' . ch . '(' . n . 'new)]' - if index(s:opened_channels, ch) == len(s:opened_channels) - 1 - let st .= '%#ChattingHI8#' . s:st_sep - elseif get(s:unread_msg_num, s:opened_channels[index(s:opened_channels, ch) + 1], 0) > 0 - \ && s:opened_channels[index(s:opened_channels, ch) + 1] !=# s:current_channel - let st .= '%#ChattingHI11#' . s:st_sep - elseif s:opened_channels[index(s:opened_channels, ch) + 1] ==# s:current_channel - let st .= '%#ChattingHI9#' . s:st_sep - else - let st .= '%#ChattingHI10#' . s:st_sep - endif - else - let st .= '%#ChattingHI3#[' . ch . ']' - if index(s:opened_channels, ch) == len(s:opened_channels) - 1 - let st .= '%#ChattingHI12#' . s:st_sep - elseif get(s:unread_msg_num, s:opened_channels[index(s:opened_channels, ch) + 1], 0) > 0 - \ && s:opened_channels[index(s:opened_channels, ch) + 1] !=# s:current_channel - let st .= '%#ChattingHI14#' . s:st_sep - elseif s:opened_channels[index(s:opened_channels, ch) + 1] ==# s:current_channel - let st .= '%#ChattingHI15#' . s:st_sep - else - let st .= '%#ChattingHI13#' . s:st_sep - endif - endif - endif - endfor - let st .= '%#ChattingHI4# ' - exe 'set statusline=' . st -endfunction - -function! s:previous_channel() abort - let id = index(s:opened_channels, s:current_channel) - let id -= 1 - if id < 0 - let id = id + len(s:opened_channels) - endif - let s:current_channel = s:opened_channels[id] - if s:current_channel =~# '^#' - call s:send('/join ' . s:current_channel) - else - call s:send('/query ' . s:current_channel) - endif - call s:update_msg_screen() - call s:update_statusline() -endfunction - -function! s:next_channel() abort - let id = index(s:opened_channels, s:current_channel) - let id += 1 - if id > len(s:opened_channels) - 1 - let id = id - len(s:opened_channels) - endif - let s:current_channel = s:opened_channels[id] - if s:current_channel =~# '^#' - call s:send('/join ' . s:current_channel) - else - call s:send('/query ' . s:current_channel) - endif - call s:update_msg_screen() - call s:update_statusline() - -endfunction - -function! s:send(msg) abort - if has('nvim') - if s:client_job_id != 0 - call jobsend(s:client_job_id, [a:msg, '']) - endif - else - call ch_sendraw(s:channel, a:msg ."\n") - endif -endfunction - -call chat#debug#defind('chatting', function('s:debug')) - diff --git a/bundle/vim-chat/autoload/chat/logger.vim b/bundle/vim-chat/autoload/chat/logger.vim index ba3d9bff9..9dc9c0a07 100644 --- a/bundle/vim-chat/autoload/chat/logger.vim +++ b/bundle/vim-chat/autoload/chat/logger.vim @@ -1,3 +1,11 @@ +"============================================================================= +" logger.vim --- logger of vim-chat +" Copyright (c) 2016-2019 Wang Shidong & Contributors +" Author: Wang Shidong < wsdjeg@outlook.com > +" URL: https://spacevim.org +" License: GPLv3 +"============================================================================= + let s:LOGGER =SpaceVim#logger#derive('vim-chat') function! chat#logger#info(msg) @@ -8,6 +16,12 @@ function! chat#logger#error(msg) call s:LOGGER.error(a:msg) endfunction +function! chat#logger#debug(msg) abort + + call s:LOGGER.debug(a:msg) + +endfunction + function! chat#logger#warn(msg) call s:LOGGER.warn(a:msg) diff --git a/bundle/vim-chat/autoload/syntax/vimchat.vim b/bundle/vim-chat/autoload/syntax/vimchat.vim deleted file mode 100644 index e69de29bb..000000000 diff --git a/bundle/vim-chat/syntax/vimchat.vim b/bundle/vim-chat/syntax/vimchat.vim index 58c5d7d73..847898038 100644 --- a/bundle/vim-chat/syntax/vimchat.vim +++ b/bundle/vim-chat/syntax/vimchat.vim @@ -6,7 +6,9 @@ " hi link vimChatMsg Comment " hi link vimChatTime String " hi link vimChatMe Type +" syn match vimChatMsg /^\[\d\d\(:\d\d\)\{0,2\}][^>]*/ contains=vimChatTime,vimChatNick syn match VimChatTime /\[\d\d\:\d\d:\d\d]/ -syn match VimChatNick /\[\d\d\:\d\d:\d\d]\s<\zs[^>]\+/ -hi def link VimChatTime Comment -hi def link VimChatNick String +syn match VimChatNick /\[\d\d\:\d\d:\d\d]\s<[^>]*>/ contains=VimChatTime +" hi def link vimChatMsg Comment +hi def link VimChatTime String +hi def link VimChatNick Type