Skip to content

Commit

Permalink
Merge pull request #70 from kamecha/refacter/message-buffer-view
Browse files Browse the repository at this point in the history
メッセージバッファでのメッセージ周りの描画を改善
  • Loading branch information
kamecha authored Dec 12, 2023
2 parents dc415a5 + fe0decb commit 4ba5aab
Show file tree
Hide file tree
Showing 6 changed files with 285 additions and 8 deletions.
99 changes: 93 additions & 6 deletions autoload/traqvim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function! traqvim#draw_timeline(bufNum) abort
for message in getbufvar(a:bufNum, "channelTimeline")
let body = traqvim#make_message_body(message, width)
let end = start + len(body) - 1
" 一度に全部描画するから、positionをここで設定する
let message.position = #{ index: index, start: start, end: end }
call setbufline(a:bufNum, start, body)
let start = end + 1
Expand All @@ -35,24 +36,93 @@ endfunction

function! traqvim#draw_forward_messages(bufNum, messages) abort
call setbufvar(a:bufNum, "&modifiable", 1)
" この関数を呼ばれる前に追加分が既にバッファ変数に登録されてる
let timeline = getbufvar(a:bufNum, "channelTimeline")
let index = len(timeline) - len(a:messages)
" startをバッファの最下値にする
let start = len(getbufline(a:bufNum, 1, '$')) + 1
let winnr = bufwinid(a:bufNum)
let width = winwidth(winnr)
for message in a:messages
let body = traqvim#make_message_body(message, width)
let end = start + len(body) - 1
let message.position = #{ index: index, start: start, end: end }
call setbufline(a:bufNum, start, body)
call appendbufline(a:bufNum, start - 1, body)
let start = end + 1
let index = index + 1
endfor
" この関数を呼ばれる前に追加分が既にバッファ変数に登録されてる
let timeline = getbufvar(a:bufNum, "channelTimeline")
call map(timeline, function("traqvim#update_message_position", [timeline]))
call setbufvar(a:bufNum, "&modifiable", 0)
endfunction

function! traqvim#draw_back_messages(bufNum, messages) abort
call setbufvar(a:bufNum, "&modifiable", 1)
let start = 1
let winnr = bufwinid(a:bufNum)
let width = winwidth(winnr)
" appendbufline()を使用する
for message in a:messages
let body = traqvim#make_message_body(message, width)
let end = start + len(body) - 1
call appendbufline(a:bufNum, start - 1, body)
let start = end + 1
endfor
" 既存のメッセージのpositionを更新する
let timeline = getbufvar(a:bufNum, "channelTimeline")
call map(timeline, function("traqvim#update_message_position", [timeline]))
call setbufvar(a:bufNum, "&modifiable", 0)
endfunction

function traqvim#draw_delete_message(bufNum, message) abort
call setbufvar(a:bufNum, "&modifiable", 1)
let start = a:message.position["start"]
let end = a:message.position["end"]
call deletebufline(a:bufNum, start, end)
" 既存のメッセージのpositionを更新する
" この関数を呼ばれる前に削除分が既にバッファ変数から削除されてる
let timeline = getbufvar(a:bufNum, "channelTimeline")
call map(timeline, function("traqvim#update_message_position", [timeline]))
call setbufvar(a:bufNum, "&modifiable", 0)
endfunction

function traqvim#draw_insert_message(bufNum, message) abort
call setbufvar(a:bufNum, "&modifiable", 1)
let prevMessage = #{}
" この関数を呼ばれる前に追加分が既にバッファ変数に登録されてる
let timeline = getbufvar(a:bufNum, "channelTimeline")
for message in timeline
if message.id == a:message.id
let prevMessage = message
break
endif
endfor
let start = 1
if !empty(prevMessage)
let start = prevMessage.position["end"] + 1
endif
let winnr = bufwinid(a:bufNum)
let width = winwidth(winnr)
let body = traqvim#make_message_body(a:message, width)
let end = start + len(body) - 1
call appendbufline(a:bufNum, start - 1, body)
" 既存のメッセージのpositionを更新する
call map(timeline, function("traqvim#update_message_position", [timeline]))
call setbufvar(a:bufNum, "&modifiable", 0)
endfunction

function! traqvim#update_message_position(timeline, key, value) abort
if a:key == 0
let start = 1
let body = traqvim#make_message_body(a:value, winwidth(bufwinid("%")))
let end = start + len(body) - 1
let a:value.position = #{ index: 0, start: start, end: end }
else
let prev = a:timeline[a:key - 1]
let start = prev.position["end"] + 1
let body = traqvim#make_message_body(a:value, winwidth(bufwinid("%")))
let end = start + len(body) - 1
let a:value.position = #{ index: a:key, start: start, end: end }
endif
return a:value
endfunction

function! traqvim#redraw_recursive(layout) abort
if a:layout[0] ==# "leaf"
let bufNum = winbufnr(a:layout[1])
Expand Down Expand Up @@ -168,6 +238,23 @@ function traqvim#yankMessageMarkdown(t) abort
call setreg(v:register, messageStart->get('content'))
endfunction

function traqvim#registerDeleteMessage() abort
let &opfunc = function('traqvim#deleteMessage')
return 'g@'
endfunction

function traqvim#deleteMessage(t) abort
if a:t != 'line'
return
endif
let messageStart = traqvim#get_message_buf(line("'["), bufnr('%'))
let messageEnd = traqvim#get_message_buf(line("']"), bufnr('%'))
if messageStart->get('id') != messageEnd->get('id')
return
endif
call denops#request('traqvim', 'messageDelete', [bufnr(), messageStart])
endfunction

function traqvim#message_motion() abort
let position = traqvim#get_message()->get('position')
call cursor(position->get('start'), 1)
Expand Down
73 changes: 71 additions & 2 deletions denops/traqvim/action.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { Denops, ensureArray, fn, helper, vars } from "./deps.ts";
import { ChannelBuffer, Message } from "./type.d.ts";
import { activity, channelMessageOptions, channelTimeline } from "./model.ts";
import {
activity,
channelMessageOptions,
channelTimeline,
deleteMessage,
editMessage,
} from "./model.ts";

export const actionOpenChannel = async (
denops: Denops,
Expand Down Expand Up @@ -75,7 +81,70 @@ export const actionBackChannelMessage = async (
backMessages.concat(timeline),
);
// 一旦全部描画するようにする
await denops.call("traqvim#draw_timeline", bufNum);
await denops.call("traqvim#draw_back_messages", bufNum, backMessages);
};

export const actionDeleteMessage = async (
denops: Denops,
message: Message,
bufNum: number,
): Promise<void> => {
try {
await deleteMessage(message.id);
} catch (e) {
console.error(e);
return;
}
// 既存メッセージの取得
const timeline = await vars.buffers.get(denops, "channelTimeline");
ensureArray<Message>(timeline);
// 削除したものをセット
await vars.buffers.set(
denops,
"channelTimeline",
timeline.filter((m) => m.id !== message.id),
);
await denops.call("traqvim#draw_delete_message", bufNum, message);
};

export const actionEditMessage = async (
denops: Denops,
message: Message,
content: string,
bufNum: number,
): Promise<void> => {
try {
await editMessage(message.id, content);
} catch (e) {
console.error(e);
return;
}
// 既存メッセージの取得
// const timeline = await vars.buffers.get(denops, "channelTimeline");
const timeline = await fn.getbufvar(denops, bufNum, "channelTimeline");
ensureArray<Message>(timeline);
const editedTimeline = timeline.map((m) => {
if (m.id === message.id) {
return {
...m,
content: content,
};
} else {
return m;
}
});
// 編集したものをセット
await fn.setbufvar(
denops,
bufNum,
"channelTimeline",
editedTimeline,
);
await denops.call(
"traqvim#draw_insert_message",
bufNum,
editedTimeline.find((m) => m.id === message.id),
);
};

export const actionOpenActivity = async (
Expand Down
77 changes: 77 additions & 0 deletions denops/traqvim/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
} from "./deps.ts";
import {
actionBackChannelMessage,
actionDeleteMessage,
actionEditMessage,
actionForwardChannelMessage,
actionOpenActivity,
actionOpenChannel,
Expand Down Expand Up @@ -260,5 +262,80 @@ export async function main(denops: Denops) {
await actionYankMessageMarkdown(denops, message as Message);
return Promise.resolve();
},
async messageDelete(bufNum: unknown, message: unknown): Promise<unknown> {
ensureNumber(bufNum);
const choice = await fn.confirm(
denops,
"Delete message?",
"&Yes\n&No",
"No",
"Warning",
);
ensureNumber(choice);
switch (choice) {
// dialogの中断
case 0:
helper.echo(denops, "make up your mind");
break;
// Yes
case 1:
helper.echo(denops, "delete message...");
await actionDeleteMessage(denops, message as Message, bufNum);
break;
// No
case 2:
helper.echo(denops, "cancel");
break;
default:
helper.echo(denops, "choice error");
break;
}
return Promise.resolve();
},
async messageEditOpen(bufNum: unknown, message: unknown): Promise<unknown> {
ensureNumber(bufNum);
await fn.setbufvar(denops, bufNum, "&splitbelow", 1);
const messageBufNum = await denops.call(
"traqvim#make_buffer",
"Edit",
"new",
);
ensureNumber(messageBufNum);
// 既存メッセージの内容を描画しておく
await fn.setbufline(
denops,
messageBufNum,
1,
(message as Message).content.split("\n"),
);
await fn.setbufvar(denops, bufNum, "&splitright", 0);
await fn.setbufvar(
denops,
messageBufNum,
"message",
message,
);
await fn.setbufvar(
denops,
messageBufNum,
"editSourceBuffer",
bufNum,
);
await denops.cmd(
"setlocal buftype=nofile ft=traqvim-message-edit nonumber breakindent",
);
return;
},
async messageEdit(
bufNum: unknown,
message: unknown,
contents: unknown,
): Promise<unknown> {
ensureNumber(bufNum);
const content = (contents as string[]).join("\n");
await actionEditMessage(denops, message as Message, content, bufNum);
await denops.cmd(":bdelete");
return;
},
};
}
33 changes: 33 additions & 0 deletions denops/traqvim/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,36 @@ export const sendMessage = async (
console.error(e);
}
};

export const deleteMessage = async (
messageId: string,
): Promise<void> => {
try {
await api.api.deleteMessage(messageId);
} catch (e) {
console.error(e);
}
};

export const editMessage = async (
messageId: string,
content: string,
): Promise<void> => {
const message: traq.PostMessageRequest = {
content: content,
embed: false,
};
const messagesJson = JSON.stringify(message);
try {
// POSTに関しては、deno&npm経由だとcontent-length等々がうまくいかないらしく、
// APIを直打ちする必要がある
await api.fetchWithToken(
"PUT",
"/messages/" + messageId,
{},
messagesJson,
);
} catch (e) {
console.error(e);
}
};
5 changes: 5 additions & 0 deletions ftplugin/traqvim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ nnoremap <buffer><expr> <Plug>(traqvim-yank-message-link-operator)
\ traqvim#registerYankMessageLink()
nnoremap <buffer><expr> <Plug>(traqvim-yank-message-markdown-operator)
\ traqvim#registerYankMessageMarkdown()
nnoremap <buffer><expr> <Plug>(traqvim-delete-message-operator)
\ traqvim#registerDeleteMessage()
onoremap <silent> <Plug>(traqvim-message-motion)
\ :<C-u>call traqvim#message_motion()<CR>
Expand All @@ -24,6 +26,9 @@ nmap <buffer> <LocalLeader>y
nmap <buffer> <LocalLeader>Y
\ <Plug>(traqvim-yank-message-markdown-operator)
nmap <buffer> <LocalLeader>d
\ <Plug>(traqvim-delete-message-operator)
command! -buffer -nargs=0 TraqYankMessageLink
\ call denops#request('traqvim', 'yankMessageLink', [traqvim#get_message()])
command! -buffer -nargs=0 TraqYankMessageMarkdown
Expand Down
6 changes: 6 additions & 0 deletions plugin/traqvim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ command! TraqFetchBack call denops#request('traqvim', 'messageBack', [bufnr(), b
command! TraqMessageOpen call denops#request('traqvim', 'messageOpen', [bufnr(), bufname()])
" messageの送信
command! TraqMessageSend call denops#request('traqvim', 'messageSend', [bufnr(), getline(1, '$')])
" messageの削除
command! TraqMessageDelete call denops#request('traqvim', 'messageDelete', [bufnr(), traqvim#get_message()])
" messageの編集
command! TraqMessageEdit call denops#request('traqvim', 'messageEditOpen', [bufnr(), traqvim#get_message()])
" messageの編集を適用
command! TraqMessageEditApply call denops#request('traqvim', 'messageEdit', [getbufvar(bufname("%"), "editSourceBuffer"), getbufvar(bufname("%"), "message"), getline(1, '$')])

call helper#define_highlight()

Expand Down

0 comments on commit 4ba5aab

Please sign in to comment.