vim: render msg table directly from cli (#238)

* vim: render msg table from cli directly

* doc: update changelog
This commit is contained in:
Clément DOUIN 2021-10-24 23:34:04 +02:00 committed by GitHub
parent e154481c5b
commit 43785b3c1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 79 deletions

View file

@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Change
- Remove error when empty subject [#229]
- Vim plugin does not render anymore the msg by itself, it uses the one available from the CLI [#220]
## [0.5.0] - 2021-10-10

View file

@ -1,34 +1,24 @@
let s:log = function("himalaya#shared#log#info")
let s:trim = function("himalaya#shared#utils#trim")
let s:cli = function("himalaya#shared#cli#call")
let s:plain_req = function("himalaya#request#plain")
let s:msg_id = 0
let s:draft = ""
" Message
function! s:format_msg_for_list(msg)
let flag_new = index(a:msg.flags, "Seen") == -1 ? "✷" : " "
let flag_flagged = index(a:msg.flags, "Flagged") == -1 ? " " : "!"
let flag_replied = index(a:msg.flags, "Answered") == -1 ? " " : "↵"
let a:msg.flags = printf("%s %s %s", flag_new, flag_replied, flag_flagged)
return a:msg
endfunction
function! himalaya#msg#list_with(account, mbox, page, should_throw)
let pos = getpos(".")
let msgs = s:cli(
\"--account %s --mailbox %s list --page %d",
\[shellescape(a:account), shellescape(a:mbox), a:page],
\printf("Fetching %s messages", a:mbox),
\a:should_throw,
\)
let msgs = map(msgs, "s:format_msg_for_list(v:val)")
let msgs = s:plain_req({
\'cmd': '--account %s --mailbox %s list --max-width %d --page %d',
\'args': [shellescape(a:account), shellescape(a:mbox), s:bufwidth(), a:page],
\'msg': printf("Fetching %s messages", a:mbox),
\'should_throw': a:should_throw,
\})
let buftype = stridx(bufname("%"), "Himalaya messages") == 0 ? "file" : "edit"
execute printf("silent! %s Himalaya messages [%s] [page %d]", buftype, a:mbox, a:page)
setlocal modifiable
silent execute "%d"
call append(0, s:render("list", msgs))
call append(0, split(msgs, '\n'))
silent execute "$d"
setlocal filetype=himalaya-msg-list
let &modified = 0
@ -315,50 +305,25 @@ function! himalaya#msg#attachments()
endtry
endfunction
" Render utils
" Utils
let s:config = {
\"list": {
\"columns": ["id", "flags", "subject", "sender", "date"],
\},
\"labels": {
\"id": "ID",
\"flags": "FLAGS",
\"subject": "SUBJECT",
\"sender": "SENDER",
\"date": "DATE",
\},
\}
" https://newbedev.com/get-usable-window-width-in-vim-script
function! s:bufwidth()
let width = winwidth(0)
let numberwidth = max([&numberwidth, strlen(line('$'))+1])
let numwidth = (&number || &relativenumber)? numberwidth : 0
let foldwidth = &foldcolumn
function! s:render(type, lines)
let s:max_widths = s:get_max_widths(a:lines, s:config[a:type].columns)
let header = [s:render_line(s:config.labels, s:max_widths, a:type)]
let line = map(copy(a:lines), "s:render_line(v:val, s:max_widths, a:type)")
return header + line
endfunction
function! s:render_line(line, max_widths, type)
return "|" . join(map(
\copy(s:config[a:type].columns),
\"s:render_cell(a:line[v:val], a:max_widths[v:key])",
\), "")
endfunction
function! s:render_cell(cell, max_width)
let cell_width = strdisplaywidth(a:cell[:a:max_width])
return a:cell[:a:max_width] . repeat(" ", a:max_width - cell_width) . " |"
endfunction
function! s:get_max_widths(msgs, columns)
let max_widths = map(copy(a:columns), "strlen(s:config.labels[v:val])")
for msg in a:msgs
let widths = map(copy(a:columns), "has_key(msg, v:val . '_len') ? msg[v:val . '_len'] : strlen(msg[v:val])")
call map(max_widths, "max([widths[v:key], v:val])")
endfor
return max_widths
if &signcolumn == 'yes'
let signwidth = 2
elseif &signcolumn == 'auto'
let signs = execute(printf('sign place buffer=%d', bufnr('')))
let signs = split(signs, '\n')
let signwidth = len(signs)>2? 2: 0
else
let signwidth = 0
endif
return width - numwidth - foldwidth - signwidth
endfunction
function! s:get_focused_msg_id()
@ -378,9 +343,9 @@ function! s:get_focused_msg_ids(from, to)
endfunction
function! s:close_open_buffers(name)
let l:open_buffers = filter(range(1, bufnr('$')), 'bufexists(v:val)')
let l:target_buffers = filter(l:open_buffers, 'buffer_name(v:val) =~ a:name')
for buffer_to_close in l:target_buffers
let open_buffers = filter(range(1, bufnr('$')), 'bufexists(v:val)')
let target_buffers = filter(open_buffers, 'buffer_name(v:val) =~ a:name')
for buffer_to_close in target_buffers
execute ":bwipeout " . buffer_to_close
endfor
endfunction

View file

@ -0,0 +1,59 @@
function! himalaya#request#json(opts)
let msg = get(a:, 'opts.msg', '')
let cmd = get(a:, 'opts.cmd', '')
let args = get(a:, 'opts.args', [])
let should_throw = get(a:, 'opts.should_throw', v:false)
call himalaya#shared#log#info(printf('%s…', msg))
let cmd = call('printf', ['himalaya --output json ' . cmd] + args)
let res = system(cmd)
if empty(res)
redraw | call himalaya#shared#log#info(printf('%s [OK]', msg))
else
try
let res = substitute(res, ':null', ':v:null', 'g')
let res = substitute(res, ':true', ':v:true', 'g')
let res = substitute(res, ':false', ':v:false', 'g')
let res = eval(res)
redraw | call himalaya#shared#log#info(printf('%s [OK]', msg))
return res.response
catch
redraw
for line in split(res, '\n')
call himalaya#shared#log#err(line)
endfor
if should_throw
throw ''
endif
endtry
endif
endfunction
function! himalaya#request#plain(opts)
let msg = get(a:opts, 'msg', '')
let cmd = get(a:opts, 'cmd', '')
let args = get(a:opts, 'args', [])
let should_throw = get(a:, 'opts.should_throw', v:false)
call himalaya#shared#log#info(printf('%s…', msg))
let cmd = call('printf', ['himalaya --output plain ' . cmd] + args)
let res = system(cmd)
if empty(res)
redraw | call himalaya#shared#log#info(printf('%s [OK]', msg))
else
try
redraw | call himalaya#shared#log#info(printf('%s [OK]', msg))
return trim(res)
catch
redraw
for line in split(res, '\n')
call himalaya#shared#log#err(line)
endfor
if should_throw
throw ''
endif
endtry
endif
endfunction

View file

@ -2,23 +2,25 @@ if exists("b:current_syntax")
finish
endif
syntax match hym_sep /|/
syntax match hym_uid /^|.\{-}|/ contains=hym_sep
syntax match hym_flags /^|.\{-}|.\{-}|/ contains=hym_uid,hym_sep
syntax match hym_subject /^|.\{-}|.\{-}|.\{-}|/ contains=hym_uid,hym_flags,hym_sep
syntax match hym_sender /^|.\{-}|.\{-}|.\{-}|.\{-}|/ contains=hym_uid,hym_flags,hym_subject,hym_sep
syntax match hym_date /^|.\{-}|.\{-}|.\{-}|.\{-}|.\{-}|/ contains=hym_uid,hym_flags,hym_subject,hym_sender,hym_sep
syntax match hym_head /.*\%1l/ contains=hym_sep
syntax match hym_unseen /^|.\{-}|✷.*$/ contains=hym_sep
syntax match HimalayaSeparator /│/
syntax match HimalayaHead /.*\%1l/ contains=HimalayaSeparator
syntax match HimalayaId /^.\{-}│/ contains=HimalayaSeparator
syntax match HimalayaFlags /^.\{-}│.\{-}│/ contains=HimalayaId,HimalayaSeparator
syntax match HimalayaSubject /^.\{-}│.\{-}│.\{-}│/ contains=HimalayaId,HimalayaFlags,HimalayaSeparator
syntax match HimalayaSender /^.\{-}│.\{-}│.\{-}│.\{-}│/ contains=HimalayaId,HimalayaFlags,HimalayaSubject,HimalayaSeparator
syntax match HimalayaDate /^.\{-}│.\{-}│.\{-}│.\{-}│.\{-}/ contains=HimalayaId,HimalayaFlags,HimalayaSubject,HimalayaSender,HimalayaSeparator
highlight hym_head term=bold,underline cterm=bold,underline gui=bold,underline
highlight hym_unseen term=bold cterm=bold gui=bold
" FIXME: Find a way to set the line bold AND to keep the style of each columns.
" syntax match HimalayaUnseen /^.\{-}│✷.*$/ contains=HimalayaSeparator
" highlight HimalayaUnseen term=bold cterm=bold gui=bold
highlight default link hym_sep VertSplit
highlight default link hym_uid Identifier
highlight default link hym_flags Special
highlight default link hym_subject String
highlight default link hym_sender Structure
highlight default link hym_date Constant
highlight HimalayaHead term=bold,underline cterm=bold,underline gui=bold,underline
highlight default link HimalayaSeparator VertSplit
highlight default link HimalayaId Identifier
highlight default link HimalayaFlags Special
highlight default link HimalayaSubject String
highlight default link HimalayaSender Structure
highlight default link HimalayaDate Constant
let b:current_syntax = "himalaya-msg-list"