mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 12:10:05 +08:00
467 lines
15 KiB
VimL
Vendored
467 lines
15 KiB
VimL
Vendored
" =============================================================================
|
|
" Filename: autoload/calendar/view.vim
|
|
" Author: itchyny
|
|
" License: MIT License
|
|
" Last Change: 2019/08/07 21:22:19.
|
|
" =============================================================================
|
|
|
|
let s:save_cpo = &cpo
|
|
set cpo&vim
|
|
|
|
function! calendar#view#new() abort
|
|
let self = copy(s:self)
|
|
call self.set_view_source(calendar#setting#get('view_source'))
|
|
call self.set_calendar_views(calendar#setting#get('views'))
|
|
call self.set_index(calendar#setting#get('view'))
|
|
call self.set_task_visibility(calendar#setting#get('task'))
|
|
return self
|
|
endfunction
|
|
|
|
let s:self = {}
|
|
|
|
let s:self.index = 0
|
|
let s:self.calendar_views = ['year', 'month', 'week', 'day_4', 'day_1', 'clock']
|
|
let s:self.index_max = len(s:self.calendar_views) - 1
|
|
let s:self.updated = 1
|
|
let s:self._help = 0
|
|
let s:self._task = 0
|
|
let s:self._event = 0
|
|
let s:self._help_order = []
|
|
let s:self._event_order = []
|
|
|
|
function! s:self.set_calendar_views(views) dict abort
|
|
let views = [ 'year', 'month', 'week', 'weekday', 'day_7', 'day_6', 'day_5', 'day_4', 'day_3', 'day_2', 'day_1', 'day', 'clock', 'event', 'agenda' ]
|
|
let calendar_views = filter(a:views, 'index(views, v:val) >= 0')
|
|
if len(calendar_views) > 0
|
|
let self.calendar_views = calendar_views
|
|
let self.index_max = len(self.calendar_views) - 1
|
|
endif
|
|
return self
|
|
endfunction
|
|
|
|
function! s:self.get_calendar_views() dict abort
|
|
return self.calendar_views[self.index]
|
|
endfunction
|
|
|
|
function! s:self.set_index(view) dict abort
|
|
let i = index(self.calendar_views, a:view)
|
|
if i < 0
|
|
if a:view ==# 'day'
|
|
let i = index(self.calendar_views, 'day_1')
|
|
elseif a:view ==# 'days'
|
|
let days = filter(copy(self.calendar_views), 'v:val =~# "^day_[2-6]"')
|
|
if len(days)
|
|
let i = index(self.calendar_views, days[0])
|
|
endif
|
|
elseif a:view ==# 'week'
|
|
let i = index(self.calendar_views, 'day_7')
|
|
endif
|
|
endif
|
|
let self.index = i < 0 ? 0 : i
|
|
let self.updated = 1
|
|
return self
|
|
endfunction
|
|
|
|
function! s:self.change_index(diff) dict abort
|
|
if calendar#setting#get('cyclic_view')
|
|
let m = self.index_max + 1
|
|
let self.index = (((self.index + a:diff) % m) + m) % m
|
|
else
|
|
let self.index = min([max([self.index + a:diff, 0]), self.index_max])
|
|
endif
|
|
let self.updated = 1
|
|
endfunction
|
|
|
|
function! s:self.event_visible() dict abort
|
|
return self._event
|
|
endfunction
|
|
|
|
function! s:self.task_visible() dict abort
|
|
return self._task
|
|
endfunction
|
|
|
|
function! s:self.set_task_visibility(_task) dict abort
|
|
let self._task = type(a:_task) == type('') ? a:_task ==# '1' : a:_task
|
|
endfunction
|
|
|
|
function! s:self.help_visible() dict abort
|
|
return self._help
|
|
endfunction
|
|
|
|
function! s:self.set_view_source(source) dict abort
|
|
let self.source = a:source
|
|
let self.views = map(deepcopy(self.source), 'calendar#view#{v:val.type}#new(v:val)')
|
|
let self.order = range(len(self.source))
|
|
return self
|
|
endfunction
|
|
|
|
function! s:self.current_view() dict abort
|
|
return self.views[self.current_view_index()]
|
|
endfunction
|
|
|
|
function! s:self.current_view_index() dict abort
|
|
let i = len(self.order) - 1
|
|
while !self.views[self.order[i]].is_visible()
|
|
let i -= 1
|
|
endwhile
|
|
return self.order[i]
|
|
endfunction
|
|
|
|
function! s:self.view_count() dict abort
|
|
let num = 0
|
|
for i in range(len(self.order))
|
|
let num += self.views[self.order[i]].is_visible()
|
|
endfor
|
|
return num
|
|
endfunction
|
|
|
|
function! s:self.visible_num() dict abort
|
|
let num = 0
|
|
for i in range(len(self.views))
|
|
if self.views[i].is_visible()
|
|
let num += 1
|
|
endif
|
|
endfor
|
|
return num
|
|
endfunction
|
|
|
|
function! s:self.event_view() dict abort
|
|
for i in range(len(self.views))
|
|
if self.views[i].source.type ==# 'event'
|
|
return self.views[i]
|
|
endif
|
|
endfor
|
|
endfunction
|
|
|
|
function! s:self.get_overlap() dict abort
|
|
let height = calendar#util#winheight()
|
|
let diffy = max([(height - self.ymax()) / 2, 0])
|
|
let o = []
|
|
let lw = []
|
|
for i in range(height)
|
|
call add(o, [])
|
|
call add(lw, [])
|
|
endfor
|
|
let f = 0
|
|
if self.visible_num() > 1
|
|
for i in range(len(self.order))
|
|
let c = self.views[self.order[i]]
|
|
if c.is_visible()
|
|
let [p, l, h, w] = [c.get_top() + (c.is_absolute() ? 0 : diffy), c.get_left(), c.sizey(), c.sizex()]
|
|
let r = range(p, p + h - 1)
|
|
for j in r
|
|
if j < len(o)
|
|
call add(o[j], i)
|
|
call add(lw[j], [l, w])
|
|
if len(o[j]) <= 1
|
|
continue
|
|
else
|
|
let f = 1
|
|
if len(o[j]) == 2
|
|
if lw[j][0][0] <= l && lw[j][0][0] + lw[j][0][1] >= l
|
|
call insert(o[j], -1)
|
|
elseif lw[j][0][0] >= l
|
|
if lw[j][0][0] < l + w
|
|
call insert(o[j], -1)
|
|
else
|
|
let o[j] = [o[j][1], o[j][0]]
|
|
endif
|
|
endif
|
|
else
|
|
call insert(o[j], -1)
|
|
endif
|
|
endif
|
|
endif
|
|
endfor
|
|
endif
|
|
endfor
|
|
endif
|
|
return [f, o, diffy]
|
|
endfunction
|
|
|
|
function! s:self.ymax() dict abort
|
|
let d = len(self.order)
|
|
let ymax = 0
|
|
for i in range(d)
|
|
let c = self.views[self.order[i]]
|
|
if c.is_visible() && !c.is_absolute()
|
|
let ymax = max([ymax, c.get_top() + c.sizey()])
|
|
endif
|
|
endfor
|
|
return ymax
|
|
endfunction
|
|
|
|
let [s:height, s:width] = [0, 0]
|
|
function! s:self.gather(...) dict abort
|
|
let d = len(self.order)
|
|
let updated = self.updated || a:0 && a:1
|
|
for i in range(d)
|
|
let c = self.views[self.order[i]]
|
|
call c.set_index(self.calendar_views[self.index])
|
|
call c.set_size()
|
|
let updated = updated || (c.is_visible() && c.updated()) " Do not break
|
|
endfor
|
|
if !updated | return 1 | endif
|
|
let self.updated = 0
|
|
let [height, width] = [calendar#util#winheight(), calendar#util#winwidth()]
|
|
if [s:height, s:width] != [height, width]
|
|
let [s:height, s:width] = [height, width]
|
|
let s:texts = map(range(s:height), 'calendar#text#new(repeat(" ", s:width), 0, v:val, "")')
|
|
let s:llen = map(range(s:height), '0')
|
|
endif
|
|
let texts = deepcopy(s:texts)
|
|
let llen = deepcopy(s:llen)
|
|
let index = self.current_view_index()
|
|
let [f, v, diffy] = self.get_overlap()
|
|
for i in range(d)
|
|
let c = self.views[self.order[i]]
|
|
if !c.is_visible()
|
|
continue
|
|
endif
|
|
call c.set_selected(self.order[i] == index)
|
|
let r = c.gather(c.is_absolute() ? 0 : diffy)
|
|
for t in r
|
|
if 0 <= t.y && t.y < height
|
|
if t.t && llen[t.y]
|
|
call t.move(llen[t.y], 0)
|
|
endif
|
|
if f && t.t
|
|
call s:split_over(t, texts, v, llen, i, height)
|
|
endif
|
|
let l = texts[t.y].over(t)
|
|
if !t.t | let llen[t.y] = l | endif
|
|
endif
|
|
endfor
|
|
endfor
|
|
return texts
|
|
endfunction
|
|
|
|
function! s:split_over(t, texts, v, llen, i, height) abort
|
|
let t = a:t
|
|
if len(t.syn) && len(t.syn[0]) == 5
|
|
let flg = 0
|
|
for k in range(len(t.syn))
|
|
for j in range(min([t.syn[k][4], a:height - t.y]))
|
|
let flg = flg || len(a:v[t.y + j]) > 1 && a:v[t.y + j][0] != a:i
|
|
endfor
|
|
if flg | break | endif
|
|
endfor
|
|
if flg
|
|
for s in t.split()
|
|
if s.y < a:height
|
|
call s.move(a:llen[s.y] - a:llen[t.y], 0)
|
|
call a:texts[s.y].over(s)
|
|
endif
|
|
endfor
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! s:self.action(action) dict abort
|
|
let ret = self.current_view().action(a:action)
|
|
if type(ret) == 0 && ret == 0
|
|
if a:action ==# 'redraw'
|
|
call b:calendar.update_force_redraw()
|
|
return 1
|
|
elseif a:action ==# 'tab'
|
|
if self.view_count() > 1 && !self.current_view().on_top()
|
|
let index = self.current_view_index()
|
|
let next = index
|
|
while !self.views[next].is_visible() || next == index
|
|
let next = (next + 1) % len(self.views)
|
|
endwhile
|
|
let idx = index(self.order, next)
|
|
if idx >= 0
|
|
call remove(self.order, idx)
|
|
let self.order = add(self.order, next)
|
|
endif
|
|
endif
|
|
elseif a:action ==# 'shift_tab'
|
|
if self.view_count() > 1 && !self.current_view().on_top()
|
|
let index = self.current_view_index()
|
|
let next = index
|
|
while !self.views[next].is_visible() || next == index
|
|
let next = (next - 1 + len(self.views)) % len(self.views)
|
|
endwhile
|
|
let idx = index(self.order, next)
|
|
if idx >= 0
|
|
call remove(self.order, idx)
|
|
let self.order = add(self.order, next)
|
|
endif
|
|
endif
|
|
elseif a:action ==# 'status'
|
|
let select = calendar#day#join_date(b:calendar.day().get_ymd())
|
|
let selectmd = calendar#day#join_date(b:calendar.day().get_ymd()[1:])
|
|
let today = calendar#day#join_date(calendar#day#today().get_ymd())
|
|
let diffnum = b:calendar.day().sub(calendar#day#today())
|
|
let diff = diffnum >= 0 ? '+' . diffnum : '' . diffnum
|
|
let todaystr = calendar#message#get('today')
|
|
let dayof = b:calendar.day().sub(b:calendar.day().year().head_day()) + 1
|
|
let yeardays = b:calendar.day().year().last_day().sub(b:calendar.day().year().head_day()) + 1
|
|
let daypercent = 100 * dayof / yeardays
|
|
let message = printf('%s %s/%s --%d%%-- %s %s %s', select, dayof, yeardays, daypercent, todaystr, today, diff)
|
|
let winw = calendar#util#winwidth() - 14
|
|
if calendar#string#strdisplaywidth(message) > winw
|
|
let message = printf('%s %s/%s --%d%%-- %s %s', select, dayof, yeardays, daypercent, today, diff)
|
|
if calendar#string#strdisplaywidth(message) > winw
|
|
let message = printf('%s %s/%s %s %s', select, dayof, yeardays, today, diff)
|
|
if calendar#string#strdisplaywidth(message) > winw
|
|
let message = printf('%s %s/%s', select, dayof, yeardays)
|
|
if calendar#string#strdisplaywidth(message) > winw
|
|
let message = printf('%s', select)
|
|
if calendar#string#strdisplaywidth(message) > winw
|
|
let message = printf('%s', selectmd)
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
call calendar#echo#message(message)
|
|
elseif a:action ==# 'today'
|
|
call b:calendar.move_day(-b:calendar.day().sub(calendar#day#today()))
|
|
call b:calendar.move_second(-b:calendar.time().sub(calendar#time#now()))
|
|
elseif a:action ==# 'help'
|
|
let self.updated = 1
|
|
let ii = -1
|
|
for i in range(len(self.order))
|
|
if self.views[i].source.type ==# 'help'
|
|
let ii = i
|
|
endif
|
|
endfor
|
|
let self._help = !self._help
|
|
if ii >= 0 && self._help
|
|
let self._help_order = copy(self.order)
|
|
let i = index(self.order, ii)
|
|
if i >= 0
|
|
call remove(self.order, i)
|
|
let self.order = add(self.order, ii)
|
|
endif
|
|
elseif has_key(self, '_help_order')
|
|
let self.order = self._help_order
|
|
let self._help = 0
|
|
endif
|
|
elseif a:action ==# 'task'
|
|
if self.current_view().on_top() && self.current_view().source.type !=# 'task'
|
|
return
|
|
endif
|
|
let self.updated = 1
|
|
let ii = -1
|
|
for i in range(len(self.order))
|
|
if self.views[i].source.type ==# 'task'
|
|
let ii = i
|
|
endif
|
|
endfor
|
|
let self._task = !self._task
|
|
if ii >= 0 && self._task
|
|
let self._task_order = copy(self.order)
|
|
let i = index(self.order, ii)
|
|
if i >= 0
|
|
let self.order = self.order[i + 1:] + self.order[:i]
|
|
endif
|
|
elseif has_key(self, '_task_order')
|
|
let self.order = self._task_order
|
|
let self._task = 0
|
|
elseif ii >= 0 && !self._task
|
|
let self.order = filter(copy(self.order), 'v:val != ii') + [ii]
|
|
endif
|
|
elseif a:action ==# 'close_task'
|
|
if self._task
|
|
call self.action('task')
|
|
endif
|
|
elseif a:action ==# 'event'
|
|
if self.current_view().on_top() && self.current_view().source.type !=# 'event'
|
|
return
|
|
endif
|
|
let self.updated = 1
|
|
let ii = -1
|
|
for i in range(len(self.order))
|
|
if self.views[i].source.type ==# 'event'
|
|
let ii = i
|
|
endif
|
|
endfor
|
|
let self._event = !self._event
|
|
if ii >= 0 && self._event
|
|
let self._event_order = copy(self.order)
|
|
let i = index(self.order, ii)
|
|
if i >= 0
|
|
let self.order = self.order[i + 1:] + self.order[:i]
|
|
endif
|
|
elseif has_key(self, '_event_order')
|
|
let self.order = self._event_order
|
|
let self._event = 0
|
|
endif
|
|
elseif a:action ==# 'close_event'
|
|
if self._event
|
|
call self.action('event')
|
|
endif
|
|
elseif a:action ==# 'hide'
|
|
try
|
|
bunload!
|
|
catch
|
|
enew!
|
|
endtry
|
|
return 1
|
|
elseif a:action ==# 'exit'
|
|
bwipeout!
|
|
return 1
|
|
elseif a:action ==# 'view_left'
|
|
call self.change_index(-v:count1)
|
|
elseif a:action ==# 'view_right'
|
|
call self.change_index(v:count1)
|
|
elseif a:action ==# 'command_enter' && mode() ==# 'c'
|
|
if getcmdtype() ==# ':'
|
|
let cmd = calendar#util#getcmdline()
|
|
let digits = []
|
|
if cmd =~# '\v^\s*marks\s*$'
|
|
call b:calendar.mark.showmarks()
|
|
return calendar#util#update_keys()
|
|
elseif cmd =~# '\v^\s*(ma%[rk]\s+|k\s*)[a-z]\s*$'
|
|
let mark = matchstr(cmd, '\v[a-z](\s*$)@=')
|
|
call b:calendar.mark.set(mark)
|
|
return calendar#util#update_keys()
|
|
elseif cmd =~# '\v^\s*delm%[arks]!\s*$'
|
|
call b:calendar.mark.delmarks()
|
|
return calendar#util#update_keys()
|
|
elseif cmd =~# '\v^\s*delm%[arks]\s+[a-z]\s*$'
|
|
let mark = matchstr(cmd, '\v[a-z](\s*$)@=')
|
|
call b:calendar.mark.delmarks(mark)
|
|
return calendar#util#update_keys()
|
|
elseif cmd =~# '\v^\s*\d+\s*$'
|
|
return calendar#util#update_keys()
|
|
elseif cmd =~# '\v^\s*\d+\s*/\s*\d+\s*(/\s*\d+\s*)?$'
|
|
let digits = map(split(cmd, '/'), 'matchstr(v:val, "\\v\\d+") * 1')
|
|
elseif cmd =~# '\v^\s*\d+\s*-\s*\d+\s*(-\s*\d+\s*)?$'
|
|
let digits = map(split(cmd, '-'), 'matchstr(v:val, "\\v\\d+") * 1')
|
|
elseif cmd =~# '\v^\s*\d+\s*\.\s*\d+\s*(\.\s*\d+\s*)?$'
|
|
let digits = map(split(cmd, '\.'), 'matchstr(v:val, "\\v\\d+") * 1')
|
|
elseif cmd =~# '\v^\s*\d+\s+\d+\s*(\s+\d+\s*)?$'
|
|
let digits = map(split(cmd, '\s\+'), 'matchstr(v:val, "\\v\\d+") * 1')
|
|
elseif cmd =~# '\v^\s*\d*\s*(\<\s*)+\d*$'
|
|
let c = matchstr(cmd, '\d\+')
|
|
let d = len(cmd) - len(substitute(cmd, '<', '', 'g'))
|
|
call self.change_index(-max([len(c) ? c + 0 : 1, 1]) * d)
|
|
return calendar#util#update_keys()
|
|
elseif cmd =~# '\v^\s*\d*\s*(\>\s*)+\d*$'
|
|
let c = matchstr(cmd, '\d\+')
|
|
let d = len(cmd) - len(substitute(cmd, '>', '', 'g'))
|
|
call self.change_index(max([len(c) ? c + 0 : 1, 1]) * d)
|
|
return calendar#util#update_keys()
|
|
endif
|
|
if len(digits)
|
|
call b:calendar.set_day(calendar#argument#day(digits, b:calendar.day().get_ymd()))
|
|
call b:calendar.set_month()
|
|
return calendar#util#update_keys()
|
|
else
|
|
return "\<CR>"
|
|
endif
|
|
else
|
|
return "\<CR>"
|
|
endif
|
|
endif
|
|
endif
|
|
return ret
|
|
endfunction
|
|
|
|
let &cpo = s:save_cpo
|
|
unlet s:save_cpo
|