Skip to content

Commit

Permalink
Merge pull request #102 from kamecha/feature/jump-message-from-quote
Browse files Browse the repository at this point in the history
引用メッセージから元メッセージへ飛べるようにした
  • Loading branch information
kamecha authored Aug 7, 2024
2 parents 4021326 + a90581b commit 312a86c
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 27 deletions.
23 changes: 22 additions & 1 deletion autoload/traqvim/message.vim
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,26 @@ function traqvim#message#get_message() abort
return traqvim#message#get_message_buf(curline, bufnr("%"))
endfunction

function traqvim#message#get_message_quote() abort
let curline = line(".")
let message = traqvim#message#get_message_buf(curline, bufnr("%"))
let quote = message->get("quote", [])
if empty(quote)
return {}
endif
let quotePos = copy(message)->get("position")->get("quote", [])
if empty(quotePos)
return {}
endif
let relativePos = curline - message.position["start"]
silent let quotePos->filter({ _, v -> v.start <= relativePos && relativePos <= v.end })
if len(quotePos) == 0
return {}
else
return quote[quotePos[0]->get("index")]
endif
endfunction

function traqvim#message#message_prev() abort
let cur = traqvim#message#get_message()
if empty(cur)
Expand Down Expand Up @@ -44,7 +64,8 @@ function traqvim#message#goto_message() abort
if empty(message)
return
endif
call denops#request('traqvim', 'timelineMessage', [message])
let quote = traqvim#message#get_message_quote()
call denops#request('traqvim', 'timelineMessage', [quote != #{} ? quote : message])
endfunction

function traqvim#message#registerYankMessageLink() abort
Expand Down
81 changes: 57 additions & 24 deletions autoload/traqvim/view.vim
Original file line number Diff line number Diff line change
@@ -1,39 +1,67 @@
" バッファ変数の情報を元に描画する関数郡

" Message { user : {id, name, displayName}, content, createdAt }
function! traqvim#view#make_message_body(message, width) abort
" return {
" body: string[],
" position: {
" quote: {
" index: number,
" start: number,
" end: number
" }[]
" }
" }
function traqvim#view#make_message_body(message, width) abort
let createdAt = denops#request('traqvim', 'convertDate', [a:message["createdAt"]])
let header = [ a:message["user"]["displayName"] . " @" . a:message["user"]["name"] . " " . createdAt, "" ]
let rows = split(a:message["content"], "\n")
let quote = []
let quotes = []
let quotePos = []
if a:message->has_key("quote")
if type(a:message["quote"]) == type([])
for q in a:message["quote"]
let createdAt = denops#request('traqvim', 'convertDate', [q["createdAt"]])
let quote += [ "", ">"]
let quote = []
let quote += [ ">" ]
let quote += [ "\t". q["user"]["displayName"] . " @" . q["user"]["name"] . " " . createdAt, "" ]
let quote += map(split(q["content"], "\n"), { _, v -> "\t" . v })
let quote += [ "", "<"]
let quotes += [ quote ]
let quotePos += [#{
\ index: len(quotes) - 1,
\ start: len(header) + len(rows) + copy(quotes)->flatten()->len() - len(quote) + 1,
\ end: len(header) + len(rows) + copy(quotes)->flatten()->len()
\}]
endfor
endif
endif
let footer = [ "", repeat("", a:width - 2) ] " 2はsigncolumnの分
let messageBody = header + rows + quote + footer
return messageBody
let messageBody = header + rows + quotes->flatten() + footer
return #{ body: messageBody, position: #{ quote: quotePos }}
endfunction

function traqvim#view#update_message_position(timeline, key, value) abort
if a:key == 0
let start = 1
let body = traqvim#view#make_message_body(a:value, winwidth(bufwinid("%")))
let end = start + len(body) - 1
let a:value.position = #{ index: 0, start: start, end: end }
let mes = traqvim#view#make_message_body(a:value, winwidth(bufwinid("%")))
let end = start + len(mes.body) - 1
let a:value.position = #{
\ index: 0,
\ start: start,
\ end: end,
\ quote: mes.position["quote"]
\}
else
let prev = a:timeline[a:key - 1]
let start = prev.position["end"] + 1
let body = traqvim#view#make_message_body(a:value, winwidth(bufwinid("%")))
let end = start + len(body) - 1
let a:value.position = #{ index: a:key, start: start, end: end }
let mes = traqvim#view#make_message_body(a:value, winwidth(bufwinid("%")))
let end = start + len(mes.body) - 1
let a:value.position = #{
\ index: a:key,
\ start: start,
\ end: end,
\ quote: mes.position["quote"]
\}
endif
return a:value
endfunction
Expand All @@ -46,11 +74,16 @@ function traqvim#view#draw_timeline(bufNum) abort
let winnr = bufwinid(a:bufNum)
let width = winwidth(winnr)
for message in getbufvar(a:bufNum, "channelTimeline")
let body = traqvim#view#make_message_body(message, width)
let end = start + len(body) - 1
let mes = traqvim#view#make_message_body(message, width)
let end = start + len(mes.body) - 1
" 一度に全部描画するから、positionをここで設定する
let message.position = #{ index: index, start: start, end: end }
call setbufline(a:bufNum, start, body)
let message.position = #{
\ index: index,
\ start: start,
\ end: end,
\ quote: mes.position["quote"]
\}
call setbufline(a:bufNum, start, mes.body)
if message->get('pinned')
call sign_place(0, "VtraQ", "pin", a:bufNum, #{ lnum: start, priority: 10 })
for i in range(start + 1, end - 1)
Expand Down Expand Up @@ -91,9 +124,9 @@ function traqvim#view#draw_forward_messages(bufNum, messages) abort
let winnr = bufwinid(a:bufNum)
let width = winwidth(winnr)
for message in a:messages
let body = traqvim#view#make_message_body(message, width)
let end = start + len(body) - 1
call appendbufline(a:bufNum, start - 1, body)
let mes = traqvim#view#make_message_body(message, width)
let end = start + len(mes.body) - 1
call appendbufline(a:bufNum, start - 1, mes.body)
if message->get('pinned')
call sign_place(0, "VtraQ", "pin", a:bufNum, #{ lnum: start, priority: 10 })
for i in range(start + 1, end - 1)
Expand All @@ -115,9 +148,9 @@ function traqvim#view#draw_back_messages(bufNum, messages) abort
let width = winwidth(winnr)
" appendbufline()を使用する
for message in a:messages
let body = traqvim#view#make_message_body(message, width)
let end = start + len(body) - 1
call appendbufline(a:bufNum, start - 1, body)
let mes = traqvim#view#make_message_body(message, width)
let end = start + len(mes.body) - 1
call appendbufline(a:bufNum, start - 1, mes.body)
if message->get('pinned')
call sign_place(0, "VtraQ", "pin", a:bufNum, #{ lnum: start, priority: 10 })
for i in range(start + 1, end - 1)
Expand Down Expand Up @@ -167,9 +200,9 @@ function traqvim#view#draw_insert_message(bufNum, message) abort
endif
let winnr = bufwinid(a:bufNum)
let width = winwidth(winnr)
let body = traqvim#view#make_message_body(a:message, width)
let end = start + len(body) - 1
call appendbufline(a:bufNum, start - 1, body)
let mes = traqvim#view#make_message_body(a:message, width)
let end = start + len(mes.body) - 1
call appendbufline(a:bufNum, start - 1, mes.body)
if a:message->get('pinned')
call sign_place(0, "VtraQ", "pin", a:bufNum, #{ lnum: start, priority: 10 })
for i in range(start + 1, end - 1)
Expand Down
16 changes: 14 additions & 2 deletions denops/@ddu-kinds/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,20 @@ export class Kind extends dduVim.BaseKind<Params> {
message,
args.previewContext.width,
);
assert(ret, is.ArrayOf(is.String));
return ret;
assert(
ret,
is.ObjectOf({
body: is.ArrayOf(is.String),
position: is.OptionalOf(is.ObjectOf({
quote: is.ArrayOf(is.ObjectOf({
index: is.Number,
start: is.Number,
end: is.Number,
})),
})),
}),
);
return ret.body;
}),
);
const timelinePreview: string[] = timelinePreviewArray.flat();
Expand Down
6 changes: 6 additions & 0 deletions denops/traqvim/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export interface Message extends traq.Message {
index: number;
start: number;
end: number;
// 相対位置の方がメッセージの位置変更に簡単に対応できそう
quote?: {
index: number;
start: number;
end: number;
}[];
};
quote?: Message[];
}
Expand Down
5 changes: 5 additions & 0 deletions denops/traqvim/type_check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ export const isMessage: Predicate<Message> = is.ObjectOf({
index: is.Number,
start: is.Number,
end: is.Number,
quote: is.OptionalOf(is.ArrayOf(is.ObjectOf({
index: is.Number,
start: is.Number,
end: is.Number,
}))),
})),
// quote?: Message[];
quote: is.OptionalOf(is.ArrayOf((x: unknown): x is Message => isMessage(x))),
Expand Down

0 comments on commit 312a86c

Please sign in to comment.