Skip to content

Commit

Permalink
VS.Vim.Window.Widget: Implement (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
hrsh7th committed Jan 10, 2021
1 parent 500db6a commit 01375e3
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 16 deletions.
16 changes: 9 additions & 7 deletions autoload/vital/__vital__/VS/Vim/Syntax/Markdown.vim
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
function! s:apply(text, ...) abort
function! s:apply(...) abort
if !exists('b:___VS_Vim_Syntax_Markdown')
runtime! syntax/markdown.vim
let b:___VS_Vim_Syntax_Markdown = {}
endif

let l:bufnr = bufnr('%')
try
for [l:mark, l:filetype] in items(s:_get_filetype_map(a:text, get(a:000, 0, {})))
for [l:mark, l:filetype] in items(s:_get_filetype_map(l:bufnr, get(a:000, 0, {})))
let l:group = substitute(toupper(l:mark), '\.', '_', 'g')
if has_key(b:___VS_Vim_Syntax_Markdown, l:group)
continue
Expand Down Expand Up @@ -35,9 +36,9 @@ endfunction
"
" _get_filetype_map
"
function! s:_get_filetype_map(text, filetype_map) abort
function! s:_get_filetype_map(bufnr, filetype_map) abort
let l:filetype_map = {}
for l:mark in s:_find_marks(a:text)
for l:mark in s:_find_marks(a:bufnr)
let l:filetype_map[l:mark] = s:_get_filetype_from_mark(l:mark, a:filetype_map)
endfor
return l:filetype_map
Expand All @@ -46,18 +47,19 @@ endfunction
"
" _find_marks
"
function! s:_find_marks(text) abort
function! s:_find_marks(bufnr) abort
let l:marks = {}

" find from buffer contents.
let l:text = join(getbufline(a:bufnr, '^', '$'), "\n")
let l:pos = 0
while 1
let l:match = matchlist(a:text, '```\s*\(\w\+\)', l:pos, 1)
let l:match = matchlist(l:text, '```\s*\(\w\+\)', l:pos, 1)
if empty(l:match)
break
endif
let l:marks[l:match[1]] = v:true
let l:pos = matchend(a:text, '```\s*\(\w\+\)', l:pos, 1)
let l:pos = matchend(l:text, '```\s*\(\w\+\)', l:pos, 1)
endwhile

return keys(l:marks)
Expand Down
77 changes: 77 additions & 0 deletions autoload/vital/__vital__/VS/Vim/Window.vim
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
function! s:_vital_loaded(V) abort
let s:Buffer = a:V.import('VS.Vim.Buffer')
endfunction

function! s:_vital_depends() abort
return ['VS.Vim.Buffer']
endfunction

let s:Do = { -> {} }

"
Expand Down Expand Up @@ -30,6 +38,75 @@ function! s:do(winid, func) abort
noautocmd keepalt keepjumps call win_gotoid(l:curr_winid)
endfunction

"
" set_var
"
function! s:set_var(win, key, value) abort
if win_gettype(a:win) !=# 'unknown'
let l:map = getwinvar(a:win, '___VS_Vim_Window', {})
let l:map[a:key] = a:value
call setwinvar(a:win, '___VS_Vim_Window', l:map)
endif
endfunction

"
" get_var
"
function! s:get_var(win, key) abort
if win_gettype(a:win) !=# 'unknown'
let l:map = getwinvar(a:win, '___VS_Vim_Window', {})
return get(l:map, a:key, v:null)
endif
return v:null
endfunction

"
" scroll
"
function! s:scroll(delta) abort
if a:delta == 0
return
endif

let l:wins = []
let l:wins += map(range(1, tabpagewinnr(tabpagenr(), '$')), 'win_getid(v:val)')
let l:wins += exists('*popup_list') ? popup_list() : []
for l:win in l:wins
if s:get_var(l:win, 'scrollable')
let l:ctx = {}
function! l:ctx.callback(win, delta) abort
try
let l:height = line('w$') - line('w0')
let l:topline = line('w0') + a:delta
let l:topline = max([l:topline, 1])
let l:topline = min([l:topline, line('$') - l:height])
let l:delta = l:topline - line('w0')
if l:delta == 0
return
endif
if win_gettype(a:win) ==# 'popup' && exists('*popup_create')
call popup_setoptions(a:win, {
\ 'firstline': l:topline,
\ })
else
call execute(printf('normal! %s%s%s%s',
\ abs(l:delta),
\ l:delta >= 0 ? "\<C-e>" : "\<C-y>",
\ abs(l:delta),
\ l:delta >= 0 ? 'j' : 'k',
\ ))
endif
catch /.*/
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
endtry
endfunction
call timer_start(0, { -> s:do(l:win, function(l:ctx.callback, [l:win, a:delta], l:ctx)) })
break
endif
endfor
return "\<Ignore>"
endfunction

"
" screenpos
"
Expand Down
68 changes: 59 additions & 9 deletions autoload/vital/__vital__/VS/Vim/Window/FloatingWindow.vim
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
function! s:_vital_loaded(V) abort
let s:Window = a:V.import('VS.Vim.Window')
endfunction

function! s:_vital_depends() abort
return ['VS.Vim.Window']
endfunction

"
" managed floating windows.
"
let s:floating_windows = {}

"
" is_available
"
Expand All @@ -9,9 +22,43 @@ function! s:is_available() abort
endfunction

"
" managed floating windows.
"
let s:floating_windows = {}
" @param {number} args.minwidth
" @param {number} args.maxwidth
" @param {number} args.minheight
" @param {number} args.maxheight
" @param {number} bufnr
"
function! s:get_size(args, bufnr) abort
let l:contents = getbufline(a:bufnr, '^', '$')
let l:maxwidth = get(a:args, 'maxwidth', -1)
let l:minwidth = get(a:args, 'minwidth', -1)
let l:maxheight = get(a:args, 'maxheight', -1)
let l:minheight = get(a:args, 'minheight', -1)

" width
let l:width = 0
for l:content in l:contents
let l:width = max([l:width, strdisplaywidth(l:content)])
endfor
let l:width = l:minwidth == -1 ? l:width : max([l:minwidth, l:width])
let l:width = l:maxwidth == -1 ? l:width : min([l:maxwidth, l:width])

" height
let l:height = len(l:contents)
for l:content in l:contents
let l:wrap = float2nr(ceil(strdisplaywidth(l:content) / str2float('' . l:width)))
if l:wrap > 1
let l:height += l:wrap - 1
endif
endfor
let l:height = l:minheight == -1 ? l:height : max([l:minheight, l:height])
let l:height = l:maxheight == -1 ? l:height : min([l:maxheight, l:height])

return {
\ 'width': max([1, l:width]),
\ 'height': max([1, l:height]),
\ }
endfunction

"
" new
Expand Down Expand Up @@ -50,12 +97,14 @@ let s:FloatingWindow = {}
"
" new
"
" @param {boolean} args.scrollable
" @param {function?} args.on_opened
" @param {function?} args.on_closed
"
function! s:FloatingWindow.new(args) abort
return extend(deepcopy(s:FloatingWindow), {
\ 'win': v:null,
\ 'scrollable': get(a:args, 'scrollable', v:false),
\ 'on_opened': get(a:args, 'on_opened', { -> {} }),
\ 'on_closed': get(a:args, 'on_closed', { -> {} }),
\ })
Expand All @@ -64,12 +113,12 @@ endfunction
"
" open
"
" @param {number} args.row 0-based indexing
" @param {number} args.col 0-based indexing
" @param {number} args.width
" @param {number} args.height
" @param {string} args.winhl
" @param {number} args.bufnr
" @param {number} args.row 0-based indexing
" @param {number} args.col 0-based indexing
" @param {number} args.width
" @param {number} args.height
" @param {string} args.winhl
" @param {number} args.bufnr
"
function! s:FloatingWindow.open(args) abort
let l:style = {
Expand All @@ -83,6 +132,7 @@ function! s:FloatingWindow.open(args) abort
call s:_move(self.win, l:style)
else
let self.win = s:_open(a:args.bufnr, l:style)
call s:Window.set_var(self.win, 'scrollable', self.scrollable)
if has('nvim')
call setwinvar(self.win, '&winhighlight', get(a:args, 'winhl', ''))
endif
Expand Down
92 changes: 92 additions & 0 deletions autoload/vital/__vital__/VS/Vim/Window/Widget/MarkupContent.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
function! s:_vital_loaded(V) abort
let s:Markdown = a:V.import('VS.Vim.Syntax.Markdown')
let s:Window = a:V.import('VS.Vim.Window')
let s:FloatingWindow = a:V.import('VS.Vim.Window.FloatingWindow')
endfunction

function! s:_vital_depends() abort
return ['VS.Vim.Syntax.Markdown', 'VS.Vim.Window', 'VS.Vim.Window.FloatingWindow']
endfunction

"
" is_available
"
function! s:is_available() abort
return s:FloatingWindow.is_available()
endfunction

"
" new
"
function! s:new(args) abort
return s:MarkupContent.new(a:args)
endfunction

let s:id = 0

let s:MarkupContent = {}

"
" new
"
" @param args.minwidth
" @param args.maxwidth
" @param args.minheight
" @param args.maxheight
"
function! s:MarkupContent.new(args) abort
let s:id += 1

let l:bufnr = bufnr(printf('VS.Vim.Window.Widget.MarkupContent:%s', s:id), v:true)
call bufload(l:bufnr)
call setbufvar(l:bufnr, '&filetype', 'markdown')
call setbufvar(l:bufnr, '&buflisted', 0)
call setbufvar(l:bufnr, '&modeline', 0)
call setbufvar(l:bufnr, '&buftype', 'nofile')
call setbufvar(l:bufnr, '&bufhidden', 'hide')
return extend(deepcopy(s:MarkupContent), {
\ 'bufnr': l:bufnr,
\ 'window': s:FloatingWindow.new({
\ 'scrollable': v:true,
\ }),
\ 'minwidth': get(a:args, 'minwidth', -1),
\ 'maxwidth': get(a:args, 'maxwidth', -1),
\ 'minheight': get(a:args, 'minheight', -1),
\ 'maxheight': get(a:args, 'maxheight', -1),
\ })
endfunction

"
" open
"
" @param {number} row
" @param {number} col
" @param {string[]} contents
"
function! s:MarkupContent.open(row, col, contents) abort
call deletebufline(self.bufnr, '^', '$')
call setbufline(self.bufnr, 1, a:contents)

let l:size = s:FloatingWindow.get_size({
\ 'minwidth': self.minwidth,
\ 'maxwidth': self.maxwidth,
\ 'minheight': self.minheight,
\ 'maxheight': self.maxheight,
\ }, self.bufnr)
call self.window.open({
\ 'bufnr': self.bufnr,
\ 'row': a:row,
\ 'col': a:col,
\ 'width': l:size.width,
\ 'height': l:size.height,
\ })
call s:Window.do(self.window.win, { -> s:Markdown.apply() })
endfunction

"
" close
"
function! s:MarkupContent.close() abort
call self.window.close()
endfunction

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
let s:expect = themis#helper('expect')
let s:MarkupContent = vital#vital#import('VS.Vim.Window.Widget.MarkupContent')

if !s:MarkupContent.is_available()
finish
endif

Describe vital#__vital__#VS#Vim#Window#Widget#MarkupContent

End

0 comments on commit 01375e3

Please sign in to comment.