mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 13:40:06 +08:00
779 lines
31 KiB
VimL
779 lines
31 KiB
VimL
" =============================================================================
|
|
" Filename: autoload/calendar/constructor/view_days.vim
|
|
" Author: itchyny
|
|
" License: MIT License
|
|
" Last Change: 2017/05/07 23:06:06.
|
|
" =============================================================================
|
|
|
|
let s:save_cpo = &cpo
|
|
set cpo&vim
|
|
|
|
function! calendar#constructor#view_days#new(instance) abort
|
|
return extend({ 'instance': a:instance }, s:constructor)
|
|
endfunction
|
|
|
|
let s:constructor = {}
|
|
|
|
function! s:constructor.new(source) dict abort
|
|
return extend(extend(s:super_constructor.new(a:source), s:instance), self.instance)
|
|
endfunction
|
|
|
|
let s:instance = {}
|
|
|
|
function! s:instance.height() dict abort
|
|
return max([self.maxheight(), 6])
|
|
endfunction
|
|
|
|
function! s:instance.on_resize() dict abort
|
|
let self.frame = copy(calendar#setting#frame())
|
|
let width = calendar#string#strdisplaywidth(self.frame.vertical)
|
|
let self.view = {}
|
|
let self.view.width = (self.sizex() - width) / self.daynum / width * width
|
|
let h = max([(self.sizey() - 3) / 6, 1])
|
|
let self.view.week_count = 5
|
|
let self.view.dayheight = h < 3 ? h : max([(self.sizey() - 3) / max([self.view.week_count, 5]), 1])
|
|
let self.view.hourheight = max([(self.sizey() - self.view.dayheight) / 24, 3])
|
|
let self.view.blockmin = 60 / (self.view.hourheight - 1)
|
|
if !(self.view.width > 3 && self.view.dayheight > 1)
|
|
let self.frame = calendar#setting#get('frame_space')
|
|
let width = 1
|
|
let self.view.width = (self.sizex() - width) / self.daynum
|
|
endif
|
|
let self.frame.width = calendar#string#strdisplaywidth(self.frame.vertical)
|
|
let self.frame.strlen = len(self.frame.vertical)
|
|
let self.element = {}
|
|
let self.element.splitter = repeat(self.frame.horizontal, (self.view.width - width) / width)
|
|
let self.element.white = repeat(' ', (self.view.width - width) / width * width)
|
|
let self.element.vwhite = self.frame.vertical . self.element.white
|
|
let self.element.format = '%2d' . repeat(' ', (self.view.width - width) / width * width - 2)
|
|
let self.view.realwidth = self.view.width - width + self.frame.strlen
|
|
let self.view.inner_width = self.view.width - width
|
|
let self.view.offset = self.view.dayheight > 1 ? 3 : 1
|
|
let self.view.locale = calendar#setting#get('locale')
|
|
call self.set_day_name()
|
|
let self._cache_key = []
|
|
endfunction
|
|
|
|
function! s:instance.width() dict abort
|
|
let frame = calendar#setting#frame()
|
|
let width = calendar#string#strdisplaywidth(frame.vertical)
|
|
let w = max([(self.maxwidth() - calendar#setting#get('clock_12hour') * 7) / 8, 3])
|
|
let hh = self.height()
|
|
let h = max([(hh - 3) / 6, 1])
|
|
let h = h < 3 ? h : max([(hh - 3) / calendar#week#week_count(b:calendar.month()), 1])
|
|
if !(w > 3 && h > 1)
|
|
let width = 1
|
|
endif
|
|
let daynum = self.daynum
|
|
if daynum == 1
|
|
let views = calendar#setting#get('views')
|
|
let i = index(views, 'day_1')
|
|
if i >= 0
|
|
let days = filter([i > 0 ? views[i - 1] : '', i + 1 < len(views) ? views[i + 1] : ''], 'v:val =~# ''^day_\d$''')
|
|
if len(days)
|
|
let num = substitute(days[0], 'day_', '', '') + 0
|
|
if 1 < num && num <= 7
|
|
let daynum = num
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
return w * 7 / daynum / width * width * daynum + width
|
|
endfunction
|
|
|
|
function! s:instance.get_min_day() dict abort
|
|
let day = b:calendar.day()
|
|
if has_key(self, 'min_day')
|
|
if day.sub(self.min_day) < 0
|
|
let self.min_day = day
|
|
elseif day.sub(self.max_day) > 0
|
|
let self.min_day = day.add(-self.daynum + 1)
|
|
endif
|
|
else
|
|
let self.min_day = day
|
|
endif
|
|
let self.max_day = self.min_day.add(self.daynum - 1)
|
|
return self.min_day
|
|
endfunction
|
|
|
|
function! s:instance.cache_key() dict abort
|
|
if has_key(self, 'min_hour') && (self.min_hour < 0 || self.max_hour > 23)
|
|
return []
|
|
else
|
|
return copy(self.min_max_hour()) + self.get_min_day().get_ymd() + [b:calendar.day().get_month()]
|
|
\ + calendar#day#today().get_ymd() + [calendar#setting#get('frame'), calendar#setting#get('first_day')]
|
|
\ + b:calendar.event.updated() + [get(g:, 'calendar_google_event_download')]
|
|
endif
|
|
endfunction
|
|
|
|
function! s:instance.min_max_hour() dict abort
|
|
let height = self.height() - self.view.offset - self.view.dayheight
|
|
let heighthour = height / self.view.hourheight
|
|
let time = b:calendar.time()
|
|
let hour = time.hour()
|
|
if has_key(self, 'min_hour')
|
|
if hour < self.min_hour
|
|
let min = hour
|
|
elseif hour > self.max_hour
|
|
let min = self.min_hour + hour - self.max_hour
|
|
else
|
|
let min = self.min_hour
|
|
endif
|
|
else
|
|
let min = time.hour() - heighthour / 2 + 2
|
|
endif
|
|
let min = max([min, 0])
|
|
let max = min([min + heighthour - 1, 23])
|
|
let min = max([max - heighthour + 1, 0])
|
|
let max = min([min + heighthour - 1, 23])
|
|
return [min, max]
|
|
endfunction
|
|
|
|
function! s:instance.set_min_max_hour(hours) dict abort
|
|
let [self.min_hour, self.max_hour] = a:hours
|
|
endfunction
|
|
|
|
function! s:instance.get_min_max_hour() dict abort
|
|
return [self.min_hour, self.max_hour]
|
|
endfunction
|
|
|
|
function! s:instance.set_day_name() dict abort
|
|
let [h, w, ww] = [self.view.dayheight, self.view.width, self.view.realwidth]
|
|
let key = h . ',' . w . ',' . ww . ',' . calendar#setting#get('frame') . ','
|
|
\ . calendar#setting#get('locale') . ',' . calendar#week#week_index(self.get_min_day()) . ',' . calendar#setting#get('first_day')
|
|
if !has_key(self, 'day_name_cache')
|
|
let self.day_name_cache = {}
|
|
endif
|
|
if has_key(self.day_name_cache, key)
|
|
let [self.day_name_text, self.day_name_syntax] = self.day_name_cache[key]
|
|
return
|
|
endif
|
|
let day_name = copy(calendar#message#get('day_name_long'))
|
|
let maxlen = max(map(copy(day_name), 'calendar#string#strdisplaywidth(v:val)'))
|
|
if maxlen >= self.view.inner_width
|
|
let day_name = copy(calendar#message#get('day_name'))
|
|
endif
|
|
let s = repeat([''], 3)
|
|
let syntax = []
|
|
let x = self.frame.strlen
|
|
let idx = self.get_min_day().week()
|
|
for i in range(idx, idx + self.daynum - 1)
|
|
if h > 1
|
|
let s[0] .= (i > idx ? self.frame.top : self.frame.topleft) . self.element.splitter
|
|
let s[2] .= (i > idx ? self.frame.junction : self.frame.left) . self.element.splitter
|
|
endif
|
|
let name = day_name[i % 7]
|
|
let wid = calendar#string#strdisplaywidth(name)
|
|
if wid >= self.view.inner_width
|
|
let name = calendar#string#truncate(name, max([2, self.view.inner_width]))
|
|
let wid = calendar#string#strdisplaywidth(name)
|
|
endif
|
|
let len = calendar#string#strdisplaywidth(self.element.splitter)
|
|
let whiteleft = repeat(' ', (len - wid) / 2)
|
|
let whiteright = repeat(' ', len - len(whiteleft) - wid)
|
|
let weekstr = whiteleft . name . whiteright
|
|
let s[h > 1] .= self.frame.vertical . weekstr
|
|
let syn = i % 7 == 0 ? 'SundayTitle' : i % 7 == 6 ? 'SaturdayTitle' : 'DayTitle'
|
|
if len(syntax)
|
|
call add(syntax[-1].syn, [syn, h > 1, x, x + len(weekstr), 0])
|
|
else
|
|
call add(syntax, calendar#text#new(len(weekstr), x, h > 1, syn))
|
|
endif
|
|
let x += len(weekstr) + self.frame.strlen
|
|
endfor
|
|
if h > 1
|
|
let s[0] .= self.frame.topright
|
|
let s[1] .= self.frame.vertical
|
|
let s[2] .= self.frame.right
|
|
endif
|
|
let self.day_name_text = s
|
|
let self.day_name_syntax = syntax
|
|
let self.day_name_cache[key] = [s, syntax]
|
|
endfunction
|
|
|
|
function! s:get_timeevts(events, blockmin) abort
|
|
let time_events = {}
|
|
let r = range(len(a:events))
|
|
for i in r
|
|
if get(a:events[i], 'isTimeEvent') && has_key(a:events[i], 'hms') && has_key(a:events[i], 'endhms')
|
|
if a:events[i].ymd == a:events[i].endymd ||
|
|
\ (a:events[i].endhms == [0, 0, 0] &&
|
|
\ calendar#day#new(a:events[i].endymd[0], a:events[i].endymd[1], a:events[i].endymd[2]).sub(
|
|
\ calendar#day#new(a:events[i].ymd[0], a:events[i].ymd[1], a:events[i].ymd[2])
|
|
\ ) == 1
|
|
\ )
|
|
let hour = a:events[i].hms[0]
|
|
let min = a:events[i].hms[1] / a:blockmin * a:blockmin
|
|
let endhour = a:events[i].ymd == a:events[i].endymd ? a:events[i].endhms[0] : 24
|
|
let endmin = a:events[i].endhms[1]
|
|
let flg = 0
|
|
let prev = []
|
|
while (hour < endhour || hour == endhour && min < endmin) && hour <= 24
|
|
let timestr = hour . ':' . min
|
|
if !has_key(time_events, timestr)
|
|
let time_events[timestr] = []
|
|
endif
|
|
call add(time_events[timestr], [i, flg, get(a:events[i], 'syntax', '')])
|
|
let prev = time_events[timestr][-1]
|
|
let flg = 1
|
|
let min += a:blockmin
|
|
if min >= 60
|
|
let min = 0
|
|
let hour += 1
|
|
endif
|
|
endwhile
|
|
if len(prev) > 1 && prev[1]
|
|
let prev[1] = 2
|
|
endif
|
|
if len(prev) && prev[1] == 0
|
|
let prev[1] = 4
|
|
endif
|
|
endif
|
|
endif
|
|
endfor
|
|
let maxnum = 0
|
|
let prevdict = {}
|
|
let hour = 0
|
|
let min = 0
|
|
let prevret = {}
|
|
let ret = {}
|
|
while hour <= 24
|
|
let timestr = hour . ':' . min
|
|
if has_key(time_events, timestr)
|
|
let maxnum = max([maxnum, len(time_events[timestr])])
|
|
let new = {}
|
|
let minind = 0
|
|
let rr = range(len(time_events[timestr]))
|
|
for i in rr
|
|
let tvs = time_events[timestr][i]
|
|
if has_key(prevdict, tvs[0])
|
|
let new[prevdict[tvs[0]]] = deepcopy(tvs)
|
|
endif
|
|
endfor
|
|
for i in rr
|
|
let tvs = time_events[timestr][i]
|
|
if !has_key(prevdict, tvs[0])
|
|
while has_key(new, minind)
|
|
let minind += 1
|
|
endwhile
|
|
let new[minind] = deepcopy(tvs)
|
|
let prevdict[tvs[0]] = minind
|
|
endif
|
|
endfor
|
|
let minind = 0
|
|
let prevret[timestr] = []
|
|
for i in range(maxnum)
|
|
if has_key(new, i)
|
|
call add(prevret[timestr], new[i])
|
|
else
|
|
call add(prevret[timestr], [-1, 3, ''])
|
|
endif
|
|
endfor
|
|
else
|
|
let prevdict = {}
|
|
for [key, events] in items(prevret)
|
|
for event in events
|
|
call add(event, maxnum)
|
|
endfor
|
|
let ret[key] = events
|
|
endfor
|
|
let prevret = {}
|
|
let maxnum = 0
|
|
endif
|
|
let min += a:blockmin
|
|
if min >= 60
|
|
let min = 0
|
|
let hour += 1
|
|
endif
|
|
endwhile
|
|
return ret
|
|
endfunction
|
|
|
|
function! s:instance.set_contents() dict abort
|
|
if self.frame.type !=# calendar#setting#get('frame') | call self.on_resize() | endif
|
|
call self.set_day_name()
|
|
let [f, v, e] = [self.frame, self.view, self.element]
|
|
let [h, w, ww] = [v.dayheight, v.width, v.realwidth]
|
|
let height = self.height() - v.offset - h
|
|
let bottompad = (self.height() - v.offset - h) % v.hourheight + 1
|
|
let self.has_today = 0
|
|
let hh = 1 <= h - 2 ? range(1, h - 2) : []
|
|
let s = repeat([''], self.sizey())
|
|
let today = calendar#day#today()
|
|
let month = b:calendar.month()
|
|
let day = b:calendar.day()
|
|
let syntax = deepcopy(self.day_name_syntax)
|
|
for i in range(len(self.day_name_text))
|
|
let s[i] = self.day_name_text[i]
|
|
endfor
|
|
let [so, st, su, sa, tsu, tsa] = ['OtherMonth', 'Today', 'Sunday', 'Saturday', 'TodaySunday', 'TodaySaturday']
|
|
let [i, j] = [0, 0]
|
|
let days = month.get_days()
|
|
let prev_days = month.add(-1).get_days()
|
|
let next_days = month.add(1).get_days()
|
|
let wn = calendar#week#week_index(days[0])
|
|
let sub = day.sub(wn ? prev_days[-wn] : days[0])
|
|
let wnum = sub / 7
|
|
let ld = wn + len(days)
|
|
let events = b:calendar.event.get_events(day.get_year(), day.get_month())
|
|
let head = self.get_min_day().sub(wn ? prev_days[-wn] : days[0])
|
|
let range = range(head, head + self.daynum - 1)
|
|
let [self.min_hour, self.max_hour] = self.min_max_hour()
|
|
let longevt = []
|
|
let longtimeevt = []
|
|
let self.timeevent_syntax = []
|
|
let event_start_time = calendar#setting#get('event_start_time')
|
|
let event_start_time_minwidth = calendar#setting#get('event_start_time_minwidth')
|
|
let clock_12hour = calendar#setting#get('clock_12hour')
|
|
for p in range
|
|
let d = p < wn ? prev_days[-wn + p] : p < ld ? days[p - wn] : next_days[p - ld]
|
|
let evts = get(events, join(d.get_ymd(), '-'), { 'events': [] } )
|
|
let y = v.offset + h * j
|
|
let s[y] .= f.vertical
|
|
let s[y] .= self.oneday(d.get_day(), evts)
|
|
let is_today = today.eq(d)
|
|
if is_today
|
|
let self.has_today = 1
|
|
endif
|
|
let syn = is_today ? st : d.is_sunday() || get(evts, 'hasHoliday') ? su : d.is_saturday() ? sa : ''
|
|
if syn !=# ''
|
|
let l = is_today ? len(calendar#string#truncate_reverse(s[y], v.inner_width)) : 2
|
|
let syn2 = !is_today ? '' : d.is_sunday() || get(evts, 'hasHoliday') ? tsu : d.is_saturday() ? tsa : ''
|
|
let x = len(calendar#string#truncate(s[y], w * i + f.width))
|
|
if syn2 !=# ''
|
|
let x += 2
|
|
let l -= 2
|
|
endif
|
|
call add(syntax, calendar#text#new(l, x, y, syn))
|
|
if syn2 !=# ''
|
|
let l = 2
|
|
let x = len(calendar#string#truncate(s[y], w * i + f.width))
|
|
if len(syntax) && syntax[-1].y == y
|
|
call add(syntax[-1].syn, [syn2, y, x, x + l, 0])
|
|
else
|
|
call add(syntax, calendar#text#new(l, x, y, syn2))
|
|
endif
|
|
endif
|
|
endif
|
|
let z = 0
|
|
let longevtIndex = 0
|
|
for x in hh
|
|
if longevtIndex < len(longevt) && longevt[longevtIndex].viewoffset == x
|
|
let lastday = d.get_day() == longevt[longevtIndex].endymd[2] ||
|
|
\ (get(longevt[longevtIndex], 'isTimeEvent') &&
|
|
\ longevt[longevtIndex].endhms == [0, 0, 0] &&
|
|
\ calendar#day#new(longevt[longevtIndex].endymd[0], longevt[longevtIndex].endymd[1], longevt[longevtIndex].endymd[2]).sub(d) == 1
|
|
\ )
|
|
let eventtext = repeat('=', v.inner_width - lastday) . (lastday ? ']' : '')
|
|
let splitter = i ? repeat('=', f.width) : f.vertical
|
|
let s[y + x] .= splitter . eventtext
|
|
if has_key(longevt[longevtIndex], 'syntax')
|
|
let l = len(eventtext)
|
|
let syn = longevt[longevtIndex].syntax
|
|
let yy = y + x
|
|
let xx = len(s[y + x]) - l - (i ? f.width : 0)
|
|
let l = l + (i ? f.width : 0)
|
|
call add(syntax, calendar#text#new(l, xx, yy, syn))
|
|
endif
|
|
let longevtIndex += 1
|
|
else
|
|
while z < len(evts.events) && (!has_key(evts.events[z], 'summary') || evts.events[z].isHoliday || evts.events[z].isMoon || evts.events[z].isDayNum || evts.events[z].isWeekNum)
|
|
let z += 1
|
|
endwhile
|
|
if z < len(evts.events)
|
|
let is_long_event = evts.events[z].ymd != evts.events[z].endymd &&
|
|
\ (!get(evts.events[z], 'isTimeEvent') ||
|
|
\ evts.events[z].endhms != [0, 0, 0] ||
|
|
\ calendar#day#new(evts.events[z].endymd[0], evts.events[z].endymd[1], evts.events[z].endymd[2]).sub(
|
|
\ calendar#day#new(evts.events[z].ymd[0], evts.events[z].ymd[1], evts.events[z].ymd[2])
|
|
\ ) > 1
|
|
\ )
|
|
if is_long_event
|
|
let trailing = ' ' . repeat('=', v.inner_width)
|
|
call add(longevt, extend(evts.events[z], { 'viewoffset': x }))
|
|
else
|
|
let trailing = ''
|
|
endif
|
|
let starttime = event_start_time && self.view.width >= event_start_time_minwidth
|
|
\ && get(evts.events[z], 'isTimeEvent') ? evts.events[z].starttime . ' ' : ''
|
|
let eventtext = calendar#string#truncate(starttime . evts.events[z].summary . trailing, v.inner_width)
|
|
if has_key(evts.events[z], 'syntax')
|
|
let l = len(eventtext)
|
|
let xx = len(s[y + x]) + len(f.vertical)
|
|
let yy = y + x
|
|
call add(syntax, calendar#text#new(l, xx, yy, evts.events[z].syntax))
|
|
endif
|
|
let s[y + x] .= f.vertical . eventtext
|
|
let z += 1
|
|
else
|
|
let s[y + x] .= e.vwhite
|
|
endif
|
|
endif
|
|
endfor
|
|
call sort(filter(longevt, 'calendar#view#month#longevt_filter(v:val, d)'), 'calendar#view#month#sorter')
|
|
let time_events = s:get_timeevts(evts.events, v.blockmin)
|
|
for k in range(height)
|
|
if k < height - bottompad
|
|
if (k + 1) % v.hourheight
|
|
let hour = self.min_hour + k / v.hourheight
|
|
let min = (k % v.hourheight) * v.blockmin
|
|
let timestr = hour . ':' . min
|
|
if has_key(time_events, timestr) && len(time_events[timestr])
|
|
let maxnum = get(time_events[timestr][0], 3, 1)
|
|
let tevts = map(deepcopy(time_events[timestr]), 'v:val[0] >= 0 ? evts.events[v:val[0]] : {}')
|
|
let onelen = max([(v.inner_width + 2) / maxnum - f.width, f.width * 3])
|
|
let hourcontents = ''
|
|
let texts = []
|
|
let syns = []
|
|
let totallen = 0
|
|
let yy = v.offset + h + k
|
|
let ya = yy - 1
|
|
let framelen = v.inner_width / f.width * f.strlen
|
|
let xx = len(s[ya]) - framelen
|
|
for ii in range(len(tevts))
|
|
let l = maxnum > 1 ? (max([0, min([onelen, v.inner_width - totallen])]) - 1) / f.width * f.width : v.inner_width
|
|
if l >= f.width * 2
|
|
let flg = time_events[timestr][ii][1]
|
|
let border = flg == 3 ? [repeat(' ', f.width), repeat(' ', f.width)] : flg == 1 ? repeat([f.vertical], 2) : [f.bottomleft, f.bottomright]
|
|
let rep = flg == 3 || flg == 1 ? repeat(' ', f.width) : f.horizontal
|
|
if flg && flg < 4
|
|
call add(texts, border[0] . repeat(rep, l / f.width - 2) . border[1])
|
|
if flg < 3
|
|
if (k % v.hourheight) == 0 && k
|
|
let cutlen = len(s[ya][(xx):])
|
|
let leftpart = s[ya][:len(s[ya]) - cutlen - 1]
|
|
let rightpart = s[ya][len(s[ya]) - cutlen + l / f.width * f.strlen :]
|
|
let s[ya] = leftpart . f.vertical . repeat(' ', l - f.width * 2) . f.vertical . rightpart
|
|
call add(syntax, calendar#text#new(l - f.width * 2 + f.strlen * 2, xx, ya, get(tevts[ii], 'syntax', '')))
|
|
let xx += l - 2 * f.width + 2 * f.strlen + f.strlen
|
|
endif
|
|
else
|
|
let xx += l / f.width * f.strlen + f.strlen
|
|
endif
|
|
else
|
|
let eventsummary = get(tevts[ii], 'summary', '')
|
|
let smallspace = repeat(' ', f.width - 1 - (calendar#string#strdisplaywidth(eventsummary) + f.width - 1) % f.width)
|
|
let newtext = calendar#string#truncate(eventsummary . smallspace . repeat(f.horizontal, l), l - f.width) . (flg ? f.horizontal : f.topright)
|
|
call add(texts, newtext)
|
|
let xx += l / f.width * f.strlen + f.strlen
|
|
endif
|
|
call add(syns, get(tevts[ii], 'syntax', ''))
|
|
let totallen += onelen
|
|
else
|
|
let xx += l / f.width * f.strlen + f.strlen
|
|
endif
|
|
endfor
|
|
let xx = len(s[yy]) + f.strlen
|
|
let hourcontents = calendar#string#truncate(join(texts, repeat(' ', f.width)), v.inner_width)
|
|
for ii in range(len(texts))
|
|
let l = len(texts[ii])
|
|
if len(syns[ii])
|
|
call extend(time_events[timestr][ii], [l, xx, yy, syns[ii]])
|
|
call add(syntax, calendar#text#new(l, xx, yy, syns[ii]))
|
|
endif
|
|
let xx += l + f.width
|
|
endfor
|
|
else
|
|
let hourcontents = e.white
|
|
endif
|
|
let s[v.offset + h + k] .= repeat(f.vertical . hourcontents, 1)
|
|
else
|
|
let s[v.offset + h + k] .= repeat(f.vertical . e.splitter, 1)
|
|
endif
|
|
endif
|
|
endfor
|
|
call add(self.timeevent_syntax, deepcopy(time_events))
|
|
if h > 1
|
|
let frame = i ? (j + 1 == 7 ? f.bottom : f.junction) : j + 1 == 7 ? f.bottomleft : f.left
|
|
let s[y + h - 1] .= frame . e.splitter
|
|
endif
|
|
if i == 6
|
|
let [i, j] = [0, j + 1]
|
|
else
|
|
let i = i + 1
|
|
endif
|
|
endfor
|
|
for i in range(1)
|
|
for j in range(h - 1)
|
|
let s[v.offset + h * i + j] .= f.vertical
|
|
endfor
|
|
let s[v.offset + h * i + h - 1] .= (i + 1 == 7 ? f.bottomright : f.right)
|
|
endfor
|
|
let s[self.height() - bottompad] .= f.bottomleft . repeat(e.splitter . f.bottom, self.daynum - 1) . e.splitter . f.bottomright
|
|
for j in range(height)
|
|
if j < height - bottompad
|
|
let s[v.offset + h + j] .= f.vertical
|
|
endif
|
|
if !((j + 1) % v.hourheight)
|
|
let hour = self.min_hour + j / v.hourheight + 1
|
|
if clock_12hour
|
|
let postfix = hour < 12 || hour == 24 ? ' a.m.' : ' p.m.'
|
|
let hour = calendar#time#hour12(hour)
|
|
else
|
|
let postfix = ''
|
|
endif
|
|
let s[v.offset + h + j] .= printf('%2d:%02d', hour, 0) . postfix
|
|
endif
|
|
if !j
|
|
let hour = self.min_hour
|
|
if clock_12hour
|
|
let postfix = ' a.m.'
|
|
let hour = calendar#time#hour12(hour)
|
|
else
|
|
let postfix = ''
|
|
endif
|
|
let s[v.offset + h - 1] .= printf('%2d:%02d', hour, 0) . postfix
|
|
endif
|
|
endfor
|
|
let self._cache_key = self.cache_key()
|
|
let self.days = map(range(len(s)), 'calendar#text#new(s[v:val], 0, v:val, "")')
|
|
let self.syntax = syntax
|
|
let self.min_day = self.get_min_day()
|
|
endfunction
|
|
|
|
function! s:instance.contents() dict abort
|
|
if self._cache_key != self.cache_key() | call self.set_contents() | endif
|
|
let [f, v, e] = [self.frame, self.view, self.element]
|
|
let select = []
|
|
let select_over = []
|
|
let cursor = []
|
|
let now = calendar#time#now()
|
|
if self.is_selected()
|
|
for [i, hour] in self.select_index()
|
|
for h in range(v.hourheight - 1)
|
|
let y = v.offset + v.dayheight + v.hourheight * (hour - self.min_hour) + h
|
|
let x = len(calendar#string#truncate(self.days[y].s, v.width * i + f.width))
|
|
let z = len(calendar#string#truncate(self.days[y].s, v.width * (i + 1)))
|
|
let timestr = hour . ':' . (v.blockmin * h)
|
|
if has_key(self.timeevent_syntax[i], timestr)
|
|
for time_event in self.timeevent_syntax[i][timestr]
|
|
if len(time_event) == 8
|
|
call add(select_over, calendar#text#new(time_event[4], time_event[5], time_event[6], time_event[7] . 'Select'))
|
|
endif
|
|
endfor
|
|
endif
|
|
call add(select, calendar#text#new(z - x, x, y, 'Select'))
|
|
endfor
|
|
endfor
|
|
let y = v.offset + v.dayheight + v.hourheight * (hour - self.min_hour)
|
|
let x = len(calendar#string#truncate(self.days[y].s, v.width * i + f.width))
|
|
let cursor = [calendar#text#new(0, x, y, 'Cursor')]
|
|
endif
|
|
if self.has_today
|
|
let i = calendar#day#today().sub(self.get_min_day())
|
|
let h = now.minute()/ (60 / (self.view.hourheight - 1))
|
|
if self.min_hour <= now.hour() && now.hour() <= self.max_hour
|
|
let y = v.offset + v.dayheight + v.hourheight * (now.hour() - self.min_hour) + h
|
|
let x = len(calendar#string#truncate(self.days[y].s, v.width * i + f.width))
|
|
let z = len(calendar#string#truncate(self.days[y].s, v.width * (i + 1)))
|
|
let nowsyn = [calendar#text#new(z - x, x, y, 'Today')]
|
|
else
|
|
let nowsyn = []
|
|
endif
|
|
else
|
|
let nowsyn = []
|
|
endif
|
|
return deepcopy(self.days) + select + deepcopy(self.syntax) + select_over + cursor + nowsyn
|
|
endfunction
|
|
|
|
function! s:instance.select_index() dict abort
|
|
let lasti = b:calendar.day().sub(self.get_min_day())
|
|
let lasthour = b:calendar.time().hour()
|
|
if !b:calendar.visual_mode()
|
|
return [[lasti, lasthour]]
|
|
endif
|
|
let last = lasti * 24 + lasthour
|
|
let starti = b:calendar.visual_start_day().sub(self.get_min_day())
|
|
let starthour = b:calendar.visual_start_time().hour()
|
|
let start = starti * 24 + starthour
|
|
let ret = []
|
|
if b:calendar.is_visual()
|
|
for i in range(min([start, last]), max([start, last]))
|
|
let j = s:div(i, 24)
|
|
let k = i - j * 24
|
|
if [j, k] != [lasti, lasthour] && 0 <= j && j < self.daynum && self.min_hour <= k && k <= self.max_hour
|
|
call add(ret, [j, k])
|
|
endif
|
|
endfor
|
|
elseif b:calendar.is_line_visual()
|
|
for j in range(min([starti, lasti]), max([starti, lasti]))
|
|
for k in range(24)
|
|
if [j, k] != [lasti, lasthour] && 0 <= j && j < self.daynum && self.min_hour <= k && k <= self.max_hour
|
|
call add(ret, [j, k])
|
|
endif
|
|
endfor
|
|
endfor
|
|
elseif b:calendar.is_block_visual()
|
|
for j in range(min([starti, lasti]), max([starti, lasti]))
|
|
for k in range(min([starthour, lasthour]), max([starthour, lasthour]))
|
|
if [j, k] != [lasti, lasthour] && 0 <= j && j < self.daynum && self.min_hour <= k && k <= self.max_hour
|
|
call add(ret, [j, k])
|
|
endif
|
|
endfor
|
|
endfor
|
|
else
|
|
endif
|
|
call add(ret, [lasti, lasthour])
|
|
return ret
|
|
endfunction
|
|
|
|
function! s:div(x, y) abort
|
|
return a:x/a:y-((a:x<0)&&(a:x%a:y))
|
|
endfunction
|
|
|
|
function! s:instance.timerange() dict abort
|
|
let hour = b:calendar.time().hour()
|
|
if !b:calendar.visual_mode()
|
|
return printf('%d:00-%d:00 ', hour, hour + 1)
|
|
endif
|
|
let x = b:calendar.day()
|
|
let xh = b:calendar.time().hour()
|
|
let y = b:calendar.visual_start_day()
|
|
let yh = b:calendar.visual_start_time().hour()
|
|
let recurrence = ''
|
|
if b:calendar.is_line_visual()
|
|
if x.sub(y) >= 0
|
|
if x.get_year() == y.get_year()
|
|
return printf('%d/%d-%d/%d ', y.get_month(), y.get_day(), x.get_month(), x.get_day()) . recurrence
|
|
else
|
|
return printf('%d/%d/%d-%d/%d/%d ', y.get_year(), y.get_month(), y.get_day(), x.get_year(), x.get_month(), x.get_day()) . recurrence
|
|
endif
|
|
else
|
|
if x.get_year() == y.get_year()
|
|
return printf('%d/%d-%d/%d ', x.get_month(), x.get_day(), y.get_month(), y.get_day()) . recurrence
|
|
else
|
|
return printf('%d/%d/%d-%d/%d/%d ', x.get_year(), x.get_month(), x.get_day(), y.get_year(), y.get_month(), y.get_day()) . recurrence
|
|
endif
|
|
endif
|
|
elseif b:calendar.is_block_visual()
|
|
if x.sub(y) >= 0
|
|
let rec = x.sub(y) + 1
|
|
let [yh, xh] = [min([xh, yh]), max([xh, yh])]
|
|
let x = y
|
|
else
|
|
let rec = y.sub(x) + 1
|
|
let [xh, yh] = [min([xh, yh]), max([xh, yh])]
|
|
let y = x
|
|
endif
|
|
let recurrence = rec > 1 ? rec . 'days ' : ''
|
|
endif
|
|
if x.sub(y) == 0 && !len(recurrence)
|
|
return printf('%d:00 - %d:00 ', min([xh, yh]), max([xh, yh]) + 1)
|
|
elseif x.sub(y) >= 0
|
|
if x.get_year() == y.get_year()
|
|
return printf('%d/%d %d:00 - %d/%d %d:00 ', y.get_month(), y.get_day(), yh, x.get_month(), x.get_day(), xh + 1) . recurrence
|
|
else
|
|
return printf('%d/%d/%d %d:00 - %d/%d/%d %d:00 ', y.get_year(), y.get_month(), y.get_day(), yh, x.get_year(), x.get_month(), x.get_day(), xh + 1) . recurrence
|
|
endif
|
|
else
|
|
if x.get_year() == y.get_year()
|
|
return printf('%d/%d %d:00 - %d/%d %d:00 ', x.get_month(), x.get_day(), xh, y.get_month(), y.get_day(), yh + 1) . recurrence
|
|
else
|
|
return printf('%d/%d/%d %d:00 - %d/%d/%d %d:00 ', x.get_year(), x.get_month(), x.get_day(), xh, y.get_year(), y.get_month(), y.get_day(), yh + 1) . recurrence
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! s:instance.action(action) dict abort
|
|
let d = b:calendar.day()
|
|
let hday = b:calendar.month().head_day()
|
|
let lday = b:calendar.month().last_day()
|
|
let hour = b:calendar.time().hour()
|
|
let wnum = d.sub(self.get_min_day())
|
|
if a:action ==# 'left'
|
|
call b:calendar.move_day(get(self, 'stopend') ? max([-v:count1, -wnum]) : -v:count1)
|
|
elseif a:action ==# 'right'
|
|
call b:calendar.move_day(get(self, 'stopend') ? min([v:count1, -wnum + self.daynum - 1]) : v:count1)
|
|
elseif index(['prev', 'next', 'space', 'add', 'subtract'], a:action) >= 0
|
|
call b:calendar.move_day(v:count1 * (index(['prev', 'subtract'], a:action) >= 0 ? -1 : 1))
|
|
elseif index(['down', 'up'], a:action) >= 0
|
|
call b:calendar.move_hour(v:count1 * (a:action ==# 'down' ? 1 : -1))
|
|
elseif index(['plus', 'minus'], a:action) >= 0
|
|
let h = v:count1 * (a:action ==# 'plus' ? 1 : -1)
|
|
while h > 23 - hour
|
|
let h = h - 24
|
|
let wnum -= self.daynum
|
|
endwhile
|
|
while h < - hour
|
|
let h = h + 24
|
|
let wnum += self.daynum
|
|
endwhile
|
|
call b:calendar.move_hour(h)
|
|
if has_key(self, 'min_day') && has_key(self, 'max_day')
|
|
if self.min_day.sub(d.add(-wnum)) > 0 || self.max_day.sub(d.add(-wnum)) < 0
|
|
let self.min_day = self.min_day.add(s:div(-wnum + self.daynum - 1, self.daynum) * self.daynum)
|
|
let self.max_day = self.max_day.add(s:div(-wnum + self.daynum - 1, self.daynum) * self.daynum)
|
|
endif
|
|
endif
|
|
call b:calendar.move_day(-wnum)
|
|
elseif index(['down_big', 'up_big'], a:action) >= 0
|
|
let diff = self.max_hour - self.min_hour
|
|
let dir = a:action ==# 'down_big' ? 1 : -1
|
|
let di = max([min([v:count1 * dir * diff * 2 / 3, 23 - hour]), - hour])
|
|
if dir > 0
|
|
let self.min_hour = self.min_hour + v:count1 * dir * diff
|
|
let self.max_hour = self.min_hour + diff
|
|
else
|
|
let self.max_hour = self.max_hour + v:count1 * dir * diff
|
|
let self.min_hour = self.max_hour - diff
|
|
endif
|
|
call b:calendar.move_hour(di)
|
|
elseif index(['down_large', 'up_large'], a:action) >= 0
|
|
let diff = self.max_hour - self.min_hour
|
|
let dir = a:action ==# 'down_large' ? 1 : -1
|
|
let di = max([min([(dir > 0 ? self.max_hour : self.min_hour) - hour + (v:count1 - 1) * dir * diff, 23 - hour]), - hour])
|
|
if dir > 0
|
|
let self.min_hour = self.min_hour + v:count1 * dir * diff
|
|
let self.max_hour = self.min_hour + diff
|
|
else
|
|
let self.max_hour = self.max_hour + v:count1 * dir * diff
|
|
let self.min_hour = self.max_hour - diff
|
|
endif
|
|
call b:calendar.move_hour(di)
|
|
elseif a:action ==# 'line_head'
|
|
call b:calendar.move_day(-wnum)
|
|
elseif a:action ==# 'line_middle'
|
|
call b:calendar.move_day(-wnum + (self.daynum - 1) / 2)
|
|
elseif a:action ==# 'line_last'
|
|
call b:calendar.move_day(self.daynum - 1 - wnum)
|
|
elseif a:action ==# 'bar'
|
|
call b:calendar.move_day(-wnum + min([v:count1 - 1, self.daynum - 1]))
|
|
elseif a:action ==# 'first_line' || a:action ==# 'first_line_head' || (a:action ==# 'last_line' && v:count)
|
|
call b:calendar.move_hour((v:count ? min([v:count1, 23]) : 0) - hour)
|
|
elseif a:action ==# 'last_line'
|
|
call b:calendar.move_hour((v:count ? max([v:count1, 23]) : 23) - hour)
|
|
elseif a:action ==# 'last_line_last'
|
|
call b:calendar.move_hour((v:count ? max([v:count1, 23]) : 23) - hour)
|
|
elseif index(['scroll_down', 'scroll_up'], a:action) >= 0
|
|
let diff = v:count1 * (a:action =~# 'down' ? 1 : -1)
|
|
let old_hours = [self.min_hour, self.max_hour]
|
|
let self.min_hour += diff
|
|
let self.max_hour += diff
|
|
let new_hours = self.min_max_hour()
|
|
if old_hours == new_hours
|
|
call b:calendar.move_hour(diff)
|
|
endif
|
|
elseif index(['scroll_top_head', 'scroll_top', 'scroll_bottom_head', 'scroll_bottom'], a:action) >= 0
|
|
let self.min_hour += 23 * (a:action =~# 'top' ? 1 : -1)
|
|
let self.max_hour += 23 * (a:action =~# 'top' ? 1 : -1)
|
|
call b:calendar.move_day(a:action =~# 'head' ? -wnum : 0)
|
|
elseif index(['scroll_center_head', 'scroll_center'], a:action) >= 0
|
|
let diff = self.max_hour - self.min_hour
|
|
let self.min_hour = hour - diff / 2 + 1
|
|
let self.max_hour = self.min_hour + diff
|
|
call b:calendar.move_day(a:action =~# 'head' ? -wnum : 0)
|
|
elseif a:action ==# 'command_enter' && mode() ==# 'c' && getcmdtype() ==# ':'
|
|
let cmd = calendar#util#getcmdline()
|
|
if cmd =~# '^\s*\d\+\s*$'
|
|
let c = max([min([matchstr(cmd, '\d\+') * 1, 23]), 0])
|
|
call b:calendar.move_hour(c - hour)
|
|
return calendar#util#update_keys()
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
let s:super_constructor = calendar#constructor#view#new(s:instance)
|
|
|
|
let &cpo = s:save_cpo
|
|
unlet s:save_cpo
|