1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 15:10:04 +08:00
SpaceVim/bundle/calendar.vim/autoload/calendar/constructor/view_months.vim

349 lines
13 KiB
VimL
Raw Normal View History

" =============================================================================
" Filename: autoload/calendar/constructor/view_months.vim
" Author: itchyny
" License: MIT License
" Last Change: 2017/05/07 23:07:32.
" =============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! calendar#constructor#view_months#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.is_full() dict abort
return self.x_months * self.y_months == 12
endfunction
function! s:instance.get_months() dict abort
if self.is_full()
return b:calendar.year().get_months()
else
let m = b:calendar.month()
let months = [m]
for i in range(self.x_months * self.y_months / 2)
call add(months, months[-1].add(1))
endfor
for i in range((self.x_months * self.y_months - 1) / 2)
call insert(months, months[0].add(-1), 0)
endfor
return months
endif
endfunction
function! s:instance.width() dict abort
let daywidth = 2
let pad = 100
while pad > daywidth * 7
let daywidth += 1
let pad = self.x_months > 1 ? max([(self.maxwidth() - daywidth * 7 * self.x_months)/2 / (self.x_months - 1), 2]) : 0
endwhile
let self.pad = pad
let self.daywidth = daywidth
return (daywidth * 7 + pad) * self.x_months - pad - self.daywidth + 2
endfunction
function! s:instance.height() dict abort
return self.y_months > 1 ? max([9, (self.maxheight()) * 4/5 / self.y_months]) * self.y_months : 9
endfunction
function! s:instance.display_point() dict abort
let w = self.maxwidth() - 2
let h = self.maxheight()
let lw = w - self.width()
let lh = (h - self.height()) * 2
return (lw >= 0 && lh >= 0) * (lw + lh + (lw - lh >= 0 ? lw - lh : - (lw - lh)) * 5)
endfunction
function! s:instance.on_resize() dict abort
let self.view = {}
let self.view.width = ((self.sizex() + self.pad + self.daywidth - 2)/ self.x_months - self.pad) / 7
let self.view.pad = self.pad
let self.view.height = self.sizey() / self.y_months
let self.view.dheight = 1
let self.view.dheight = max([1, self.view.height / 8])
let self.view.offset = self.view.dheight * 2
let self.element = {}
let self.element.pad = repeat(' ', self.view.pad)
let self.element.format = '%2d' . repeat(' ', self.view.width - 2)
let self.element.white = repeat(' ', self.view.width)
let self._today = [0, 0, 0]
let self._month = [0, 0]
let self._year = 0
call self.set_day_name()
endfunction
function! s:instance.set_day_name() dict abort
let day_name = copy(calendar#message#get('day_name'))
let [v, e] = [self.view, self.element]
let [mh, h, w] = [v.dheight, v.height, v.width]
let syntax = []
let day_names = ''
let offsetx = [0]
let index = calendar#week#first_day_index()
for i in range(index, index + 6)
let name = day_name[i % 7]
let day_names .= calendar#string#truncate(name, 2) . repeat(' ', self.view.width - 2)
call add(offsetx, len(day_names))
endfor
for j in range(self.y_months)
let y = h * j + v.offset / 2
let f = 1
let daytitles = []
for i in range(self.x_months)
call add(daytitles, calendar#text#new(len(day_names) - (self.view.width - 2), (offsetx[-1] + v.pad) * i, y, 'DayTitle'))
for k in range(index, index + 6)
let l = k % 7
let is_sunday = l == 0
let is_saturday = l == 6
if is_sunday || is_saturday
let x = (offsetx[-1] + v.pad) * i + offsetx[k - index]
let name = day_name[l]
let weekstr = calendar#string#truncate(name, 2)
let syn = is_sunday ? 'SundayTitle' : is_saturday ? 'SaturdayTitle' : ''
call daytitles[-1].over(calendar#text#new(len(weekstr), x, y, syn))
endif
endfor
endfor
for i in range(len(daytitles))
if i
call extend(syntax[-1].syn, daytitles[i].syn)
else
call add(syntax, daytitles[i])
endif
endfor
endfor
let self.day_name_texts = syntax
let self.day_names = day_names
let self.day_names_len = offsetx[-1]
let self._first_day = calendar#setting#get('first_day')
endfunction
function! s:instance.changed() dict abort
if self._today != calendar#day#today().get_ymd() || get(self, '_first_day', '') != calendar#setting#get('first_day')
return 1
elseif self.is_full()
return self._year != b:calendar.year().get_y()
else
return self._month != b:calendar.month().get_ym()
endif
endfunction
function! s:instance.set_contents() dict abort
let month_name = copy(calendar#message#get('month_name_long'))
let self.month_names_offset = []
for i in range(self.y_months)
call add(self.month_names_offset, [])
endfor
let year = b:calendar.year()
let month = b:calendar.month()
let s = repeat([''], self.sizey())
let syntax = deepcopy(self.day_name_texts)
let [v, e] = [self.view, self.element]
let [mh, h, w] = [v.dheight, v.height, v.width]
let [i, j] = [0, 0]
let today = calendar#day#today()
let self.sun_position = []
let self.sat_position = []
let self.top_syntax = []
let months = self.get_months()
let week_number = calendar#setting#get('week_number')
for m in months
if len(s[h * j])
for mj in range(h)
let s[mj + h * j] .= mj < v.offset ? e.pad : e.pad[2:]
endfor
endif
let [mi, mj] = [0, 0]
let monthname = month_name[m.get_month() - 1]
let monthnamelen = calendar#string#strdisplaywidth(monthname)
let holidays = b:calendar.event.get_holidays(m.get_year(), m.get_month())
call add(self.month_names_offset[j], len(s[mh * mj + h * j]))
if monthnamelen >= w * 6 + 2
let s[mh * mj + h * j] .= calendar#string#truncate(monthname, w * 7 - 1) . ' '
else
let whiteleft = (w * 6 + 3 - monthnamelen) / 2
let whiteright = w * 7 - monthnamelen - whiteleft
let s[mh * mj + h * j] .= repeat(' ', whiteleft) . monthname . repeat(' ', whiteright)
endif
call add(self.month_names_offset[j], len(s[mh * mj + h * j]))
let s[mh * mj + h * j + v.offset / 2] .= self.day_names
let days = m.get_days()
let prev_days = calendar#week#is_first_day(days[0]) ? [] : m.add(-1).get_days()
let next_days = calendar#week#is_last_day(days[-1]) ? [] : m.add(1).get_days()
let week_count = calendar#week#week_count(m)
let wn = calendar#week#week_index(days[0])
let ld = wn + len(days)
let sun = [-1, -1, -1]
let sat = [-1, -1, -1]
for p in range(week_count * 7)
let d = p < wn ? prev_days[-wn + p] : p < ld ? days[p - wn] : next_days[p - ld]
let x = (w * 7 + v.pad) * i + v.width * mi
let y = mh * mj + h * j + v.offset
if wn <= p && p < ld
let s[y] .= printf(e.format, d.get_day())
if today.eq(d)
for k in range(mh) " Do not use .height()
call add(self.top_syntax, calendar#text#new(2, x, y + k, 'Today'))
endfor
elseif has_key(holidays, join(d.get_ymd(), '-'))
for k in range(mh) " Do not use .height()
call add(self.top_syntax, calendar#text#new(2, x, y + k, 'Sunday'))
endfor
elseif d.is_sunday()
if sun[0] < 0 | let sun[0] = x | endif
let sun[2 - (sun[1] < 0)] = y
elseif d.is_saturday()
if sat[0] < 0 | let sat[0] = x | endif
let sat[2 - (sat[1] < 0)] = y
endif
let dd = d
else
let s[y] .= e.white
endif
if mi == 6
let [mi, mj] = [0, mj + 1]
if week_number
call add(self.top_syntax, calendar#text#new(2, len(s[y]), y, 'Comment'))
let s[y] .= printf('%2d', calendar#week#week_number(dd))
else
let s[y] .= ' '
endif
else
let mi = mi + 1
endif
endfor
if sun[0] >= 0
if sun[2] < 0 | let sun[2] = sun[1] | endif
if len(syntax) && syntax[-1].y == sun[1]
call add(syntax[-1].syn, ['Sunday', sun[1], sun[0], sun[0] + 2, sun[2] - sun[1] + mh])
elseif len(syntax) > 1 && syntax[-2].y == sun[1]
call add(syntax[-2].syn, ['Sunday', sun[1], sun[0], sun[0] + 2, sun[2] - sun[1] + mh])
else
call add(syntax, calendar#text#new(2, sun[0], sun[1], 'Sunday').height(sun[2] - sun[1] + mh))
endif
endif
if sat[0] >= 0
if sat[2] < 0 | let sat[2] = sat[1] | endif
if len(syntax) && syntax[-1].y == sat[1]
call add(syntax[-1].syn, ['Saturday', sat[1], sat[0], sat[0] + 2, sat[2] - sat[1] + mh])
elseif len(syntax) > 1 && syntax[-2].y == sat[1]
call add(syntax[-2].syn, ['Saturday', sat[1], sat[0], sat[0] + 2, sat[2] - sat[1] + mh])
else
call add(syntax, calendar#text#new(2, sat[0], sat[1], 'Saturday').height(sat[2] - sat[1] + mh))
endif
endif
call add(self.sun_position, sun)
call add(self.sat_position, sat)
for jj in range(mj, h - v.offset)
let y = mh * jj + h * j + v.offset
if y < len(s) && y < h * (j + 1)
let s[y] .= repeat(e.white, 7) . ' '
else
break
endif
endfor
if i == self.x_months - 1 | let [i, j] = [0, j + 1] | else | let i = i + 1 | endif
if j >= self.y_months | break | endif
endfor
let self._today = today.get_ymd()
let self._first_day = calendar#setting#get('first_day')
if self.is_full()
let self._year = b:calendar.year().get_y()
else
let self._month = b:calendar.month().get_ym()
endif
let self.days = map(range(len(s)), 'calendar#text#new(s[v:val], 0, v:val, "")')
let self.syntax = syntax
endfunction
function! s:instance.contents() dict abort
if get(self, '_first_day', '') != calendar#setting#get('first_day') | call self.on_resize() | endif
if self.changed() | call self.set_contents() | endif
let [v, e] = [self.view, self.element]
let [mh, h, w] = [v.dheight, v.height, v.width]
let select = []
let month = b:calendar.month()
let ij = month.sub(self.get_months()[0])
let [i, j] = [ij % self.x_months, ij / self.x_months]
let o = self.month_names_offset[j]
let sunsat = []
if self.is_selected()
for x in range(calendar#week#week_count(month) * mh + v.offset)
let l = x ? (x > 1 ? w * 7 : self.day_names_len) : o[i * 2 + 1] - o[i * 2]
let offset = x ? ((x > 1 ? w * 7 : self.day_names_len) + v.pad) * i : o[i * 2]
if x != mh
call add(select, calendar#text#new(l - (self.view.width - 2), offset, h * j + x, 'Select'))
endif
endfor
call add(select, calendar#text#new(0, o[i * 2], h * j, 'Cursor'))
let sun = self.sun_position[ij]
for j in range(sun[2] - sun[1] + mh - 1)
call add(sunsat, calendar#text#new(2, sun[0], sun[1] + j + 1, ''))
endfor
let sat = self.sat_position[ij]
for j in range(sat[2] - sat[1] + mh - 1)
call add(sunsat, calendar#text#new(2, sat[0], sat[1] + j + 1, ''))
endfor
endif
return deepcopy(self.days) + select + deepcopy(self.syntax) + sunsat + deepcopy(self.top_syntax)
endfunction
function! s:instance.action(action) dict abort
let month = b:calendar.month()
let months = self.get_months()
let ij = month.sub(months[0])
let [x, y] = [self.x_months, self.y_months]
let [i, j] = [ij % x, ij / x]
if a:action ==# 'left'
call b:calendar.move_month(self.is_full() ? max([-v:count1, - i]) : -v:count1 * y)
elseif a:action ==# 'right'
call b:calendar.move_month(self.is_full() ? min([v:count1, x - 1 - i]) : v:count1 * y)
elseif index(['prev', 'next', 'space', 'add', 'subtract'], a:action) >= 0
call b:calendar.move_month(v:count1 * (a:action ==# 'prev' || a:action ==# 'subtract' ? -1 : 1))
elseif index(['down', 'up', 'scroll_down', 'scroll_up'], a:action) >= 0
call b:calendar.move_month(v:count1 * (a:action =~# 'down' ? 1 : -1) * x)
elseif index(['plus', 'minus'], a:action) >= 0
call b:calendar.move_month(v:count1 * (a:action ==# 'plus' ? 1 : -1) * x - i)
elseif index(['down_big', 'up_big'], a:action) >= 0
call b:calendar.move_month(v:count1 * (a:action ==# 'down_big' ? 1 : -1) * (self.is_full() ? x * 2 : len(months)))
elseif index(['down_large', 'up_large'], a:action) >= 0
call b:calendar.move_year(v:count1 * (a:action ==# 'down_large' ? 1 : -1))
elseif a:action ==# 'line_head'
call b:calendar.move_month(self.is_full() ? -i : -x * y / 2)
elseif a:action ==# 'line_middle'
call b:calendar.move_month(self.is_full() ? (x - 1) / 2 - i : 0)
elseif a:action ==# 'line_last'
call b:calendar.move_month(self.is_full() ? x - 1 - i : x * y / 2)
elseif a:action ==# 'bar'
call b:calendar.move_month(min([v:count1, x]) - (self.is_full() ? i + 1 : (x + 1) / 2))
elseif a:action ==# 'first_line' || a:action ==# 'first_line_head'
call b:calendar.move_month(- ij)
elseif a:action ==# 'last_line'
call b:calendar.move_month(-month.sub(months[-x]))
elseif a:action ==# 'last_line_last'
call b:calendar.move_month(-month.sub(months[-1]))
elseif a:action ==# 'command_enter' && mode() ==# 'c' && getcmdtype() ==# ':'
let cmd = calendar#util#getcmdline()
if cmd =~# '^\s*\d\+\s*$'
let c = max([min([cmd * 1, 12]), 1])
call b:calendar.move_month(c - month.get_month())
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