Initial commit.

This commit is contained in:
yan
2011-11-17 15:45:33 -06:00
commit 882015bc6d
1819 changed files with 111625 additions and 0 deletions

View File

@@ -0,0 +1,571 @@
" Author: Mykola Golubyev ( Nickolay Golubev )
" Email: golubev.nikolay@gmail.com
" Site: www.railmoon.com
" Module: railmoon#widget#base
" Purpose: base widget functionality and vim windows triggers handler
" -
" [ internal usage ]
" Purpose: collect widget that will be closed
" -
let s:widget_for_close = []
function! s:clear_widget_for_close()
let s:widget_for_close = []
endfunction
function! s:widget_present(list, widget)
for widget in a:list
if widget.id == a:widget.id
return 1
endif
endfor
return 0
endfunction
function! s:add_widget_for_close(widget)
if s:widget_present(s:widget_for_close, a:widget)
return
endif
call add(s:widget_for_close, a:widget)
endfunction
function! s:remove_widget_from_delete(widget)
if ! s:widget_present(s:widget_for_close, a:widget)
return
endif
call filter(s:widget_for_close, 'v:val.id != '.a:widget.id)
endfunction
let s:buffer_name_prefix = 'rmwidget'
let s:in_create_widget_state = 0
" -
" [ public for extend library function ]
" Name: railmoon#widget#base#create
" Purpose: create base widget
" [ parameters ]
" name widget window name
" titlename name that will on title bar
" child widget that inherit base
" child_callback_object call back object with following methods that child can
" react on
" on_close
" on_close_with_tab_page
" on_focus
" on_focus_lost
" on_setup
" callback_object user defined call back object
" -
function! railmoon#widget#base#create(name, titlename, child, child_callback_object, callback_object)
call s:clear_widget_for_close()
let new_object = extend( deepcopy(s:base), deepcopy(a:child) )
call railmoon#trace#debug('create base:'.a:name)
call railmoon#trace#debug(string(new_object))
" if bufexists(escaped_name)
" throw 'widget:base:buffer_exists'
" endif
let new_object.id = railmoon#id#acquire('railmoon_widget_id')
let new_object.name = a:name
let new_object.titlename = a:titlename
let new_object.child_callback_object = a:child_callback_object
let new_object.callback_object = a:callback_object
let new_object.is_closed = 0
let buffer_name = s:buffer_name_prefix.new_object.id
let s:in_create_widget_state = 1
let buffer_number = bufnr( buffer_name )
if -1 == buffer_number
exec 'silent edit '.buffer_name
else
exec 'silent buffer '.buffer_number
endif
exec 'setlocal statusline='.escape(new_object.name, ' ')
setlocal noreadonly
let w:widget_id = new_object.id
let w:widget = new_object
let b:widget_id = new_object.id
let b:widget = new_object
call s:buffer_auto_command_setup()
call s:buffer_setup()
let s:in_create_widget_state = 0
return new_object
endfunction
" -
" [ internal usage ]
" Name: railmoon#widget#base#call_back
" Purpose: call back method for handlers
" -
function! railmoon#widget#base#call_back(widget, method_name, ... )
let arguments = join(a:000, ';')
call railmoon#trace#debug('call back for widget. name:'. a:widget.name. '; method:'.a:method_name.' ; arguments:'.arguments)
let exec_line = 'call object.'.a:method_name.'('.arguments.')'
for object in [ a:widget.child_callback_object, a:widget.callback_object ]
if has_key(object, a:method_name)
call railmoon#trace#debug(exec_line)
exec exec_line
endif
endfor
endfunction
" -
" [ internal usage ]
" Name: buffer_option_setup
" Purpose: setup common local options for widget buffer
" -
function! s:buffer_option_setup()
setlocal noswapfile
setlocal nomodifiable
setlocal bufhidden=delete
setlocal buftype=nofile
setlocal nobuflisted
setlocal nonumber
setlocal nowrap
setlocal nocursorline
endfunction
function! s:redraw_widget()
if has_key(b:widget, 'draw')
call b:widget.draw()
endif
endfunction
" -
" [ internal usage ]
" Name: buffer_setup
" Purpose: when buffer needs to be resetup. after reopen in widget window
" -
function! s:buffer_setup()
call s:buffer_option_setup()
let b:widget = w:widget
let b:widget_id = w:widget_id
call s:set_widget_title()
if s:in_create_widget_state
return
endif
call railmoon#widget#base#call_back(b:widget, 'on_setup')
call s:redraw_widget()
endfunction
" -
" [ internal usage ]
" Name: buffer_auto_command_setup
" Purpose: setup common handlers for window triggers
" -
function! s:buffer_auto_command_setup()
autocmd! * <buffer>
autocmd BufWinLeave <buffer> call s:on_buffer_win_leave()
autocmd WinEnter <buffer> call s:on_window_enter()
autocmd WinLeave <buffer> call s:on_window_leave()
autocmd TabLeave <buffer> call s:on_tab_leave()
endfunction
" -
" [ internal usage ]
" Name: auto_command_setup
" Purpose: setup handlers for any window or buffer to resolve conflicts
" -
function! s:auto_command_setup()
augroup base_widget_autocommands
autocmd!
autocmd WinEnter * call s:on_any_window_enter()
autocmd BufEnter * call s:on_any_buffer_enter()
autocmd BufWinEnter * call s:on_any_buffer_window_enter()
" autocmd BufWinLeave * call s:on_any_buffer_win_leave()
augroup END
endfunction
function! s:widget_in_auto_command()
let buffer_name = expand('<afile>')
let widget = getbufvar(buffer_name, 'widget')
if empty(widget)
throw 'widget not found!!!! TODO'
endif
return widget
endfunction
function! s:on_any_buffer_window_enter()
call railmoon#trace#push('on_any_buffer_window_enter')
try
let buffer_name = expand('<afile>')
call railmoon#trace#debug('name: '.buffer_name)
if empty(buffer_name) " TODO
return
endif
if ! railmoon#widget#handle_autocommands()
call railmoon#trace#debug('handle autocommands stoped')
return
endif
if exists('w:widget_id') && !exists('b:widget_id')
call railmoon#trace#debug('w:widget_id present but b:widget_id not')
call s:remove_widget_from_delete(w:widget)
let buffer_number = bufnr(s:buffer_name_prefix.w:widget_id)
let buffer_change_cmd = 'buffer '.buffer_number
call railmoon#trace#debug(buffer_change_cmd)
exec buffer_change_cmd
call s:buffer_setup()
return
endif
if exists('b:widget_id') && !exists('w:widget_id')
call railmoon#trace#debug('b:widget exists but w:widget not')
close
return
endif
catch /.*/
echo v:exception
call railmoon#trace#debug(v:exception)
finally
if exists('w:widget')
call s:remove_widget_from_delete(w:widget)
endif
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ internal usage ]
" Name: on_buffer_win_leave
" Purpose: handle widget close event
" -
function! s:on_buffer_win_leave()
call railmoon#trace#push('on_buffer_win_leave')
try
let widget = s:widget_in_auto_command()
call railmoon#trace#debug('widget for close set up')
call s:add_widget_for_close(widget)
if widget.is_closed
call railmoon#trace#debug('already closed')
return
endif
let buffer_name = expand('<afile>')
" closed by close tab page
" TODO find out another cases
" when <afile> != %
if buffer_name != bufname('%')
let s:close_with_tab_page = 1
" TODO s:close_with_tab_page
else
let s:close_with_tab_page = 0
endif
finally
call s:close_ready_for_close_widgets()
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
function! railmoon#widget#base#gui_tab_label()
if v:lnum == s:current_tab_page_number
return s:current_widget_name
endif
" let old_line = s:old_gui_tab_label
" let old_line = substitute(old_line, '%{\(.\{-}\)}', '\1', 'g')
" return eval(old_line)
return ''
endfunction
function! railmoon#widget#base#tab_line()
return s:current_widget_name
endfunction
function! s:set_widget_title()
let s:current_tab_page_number = tabpagenr()
let s:current_widget_name = b:widget.name
let s:current_widget_title_name = b:widget.titlename
if ! exists('s:old_title_string')
let s:old_title_string = &titlestring
let s:old_gui_tab_label = &guitablabel
let s:old_tab_line = &tabline
endif
let &titlestring = s:current_widget_title_name
set guitablabel=%{railmoon#widget#base#gui_tab_label()}
set tabline=%!railmoon#widget#base#tab_line()
exec 'setlocal statusline='.escape(s:current_widget_name, ' ')
endfunction
function! s:restore_original_title()
if exists('s:old_title_string')
let &titlestring = s:old_title_string
let &guitablabel = s:old_gui_tab_label
let &tabline = s:old_tab_line
unlet s:old_title_string
unlet s:old_gui_tab_label
endif
endfunction
" -
" [ internal usage ]
" Name: on_window_enter
" Purpose: handle gain focus event
" -
function! s:on_window_enter()
call railmoon#trace#push('on_window_enter')
try
let widget = s:widget_in_auto_command()
call s:set_widget_title()
call railmoon#widget#base#call_back(widget, 'on_focus')
catch /widget not found/
call railmoon#trace#debug(v:exception)
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
function! s:on_any_buffer_enter()
call railmoon#trace#push('on_any_buffer_enter')
try
if ! railmoon#widget#handle_autocommands()
call railmoon#trace#debug('handle autocommands stoped')
return
endif
let buffer_name = expand('<afile>')
call railmoon#trace#debug('buffer name:'.buffer_name)
call railmoon#trace#debug('in_create_widget_state:'.s:in_create_widget_state)
" attempt to edit file with name reserved to widget buffers
"
if !exists('b:widget_id') && ! s:in_create_widget_state
call railmoon#trace#debug('b:widget not found')
if buffer_name =~ s:buffer_name_prefix
call railmoon#trace#debug('name of widget buffer')
if buffer_name == expand('%')
call railmoon#trace#debug('open alternate window')
buffer #
endif
endif
"
" attempt to re open widget buffer
elseif exists('b:widget_id') && ! s:in_create_widget_state
call railmoon#widget#base#call_back(b:widget, 'on_setup')
call s:redraw_widget()
endif
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
function! s:close_ready_for_close_widgets()
call railmoon#trace#push('s:close_ready_for_close_widgets()')
try
for widget in s:widget_for_close
call railmoon#trace#debug('s:widget_for_close exists')
if widget.is_closed
call railmoon#trace#debug('already closed')
else
if s:close_with_tab_page
call railmoon#widget#base#call_back(widget, 'on_close_with_tab_page')
else
call railmoon#widget#base#call_back(widget, 'on_close')
endif
let widget.is_closed = 1
call railmoon#id#release('railmoon_widget_id', widget.id)
endif
endfor
call s:clear_widget_for_close()
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
function! s:on_any_window_enter()
call railmoon#trace#push('on_any_window_enter')
try
call railmoon#trace#debug('name: '.expand('<afile>'))
if ! railmoon#widget#handle_autocommands()
call railmoon#trace#debug('handle autocommands stoped')
return
endif
call s:close_ready_for_close_widgets()
" split or something like that
if exists('b:widget_id') && !exists('w:widget_id') && ! s:in_create_widget_state
call railmoon#trace#debug('b:widget_id present but w:widget_id not')
call railmoon#trace#debug('closing')
close
endif
if exists('w:widget_id') && !exists('b:widget_id')
call railmoon#trace#debug('w:widget_id present but b:widget_id not')
close
endif
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ internal usage ]
" Name: on_tab_leave
" Purpose: handle tab page lost focus event
" -
function! s:on_tab_leave()
call railmoon#trace#push('on_window_leave')
try
call railmoon#widget#base#call_back(b:widget, 'on_tab_leave')
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ internal usage ]
" Name: on_window_leave
" Purpose: handle lost focus event
" -
function! s:on_window_leave()
call railmoon#trace#push('on_window_leave')
try
if !exists('b:widget')
call railmoon#trace#debug('b:widget not present')
return
endif
if b:widget.is_closed
call railmoon#trace#debug('already closed')
return
endif
call railmoon#widget#base#call_back(b:widget, 'on_focus_lost')
catch /.*/
call railmoon#trace#debug(v:exception)
call railmoon#trace#debug(v:throwpoint)
finally
call s:restore_original_title()
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ internal usage ]
" Name: base
" Purpose: base widget object
" -
let s:base = {}
function! s:base.select()
call railmoon#trace#push('base.select')
try
let id = self.id
call railmoon#trace#debug('selecting...')
call railmoon#widget#window#select(id)
finally
call railmoon#trace#debug('id = '.id)
call railmoon#trace#pop()
endtry
endfunction
function! s:base.close()
call railmoon#trace#push('base.close')
try
if self.is_closed
call railmoon#trace#debug('already closed')
return
endif
let not_active = (w:widget_id != self.id)
if not_active
let selected = railmoon#widget#window#save_selected()
endif
call self.select()
call railmoon#trace#debug('closing.. id = '.self.id)
let window_numbers = winnr('$')
let self.is_closed = 1
close
if not_active
call railmoon#widget#window#load_selected(selected)
endif
call railmoon#id#release('railmoon_widget_id', self.id)
if window_numbers > 1
call railmoon#widget#base#call_back(self, 'on_close')
else
call railmoon#widget#base#call_back(self, 'on_close_with_tab_page')
endif
finally
call s:close_ready_for_close_widgets()
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
call s:auto_command_setup()

View File

@@ -0,0 +1,82 @@
" Author: Mykola Golubyev ( Nickolay Golubev )
" Email: golubev.nikolay@gmail.com
" Site: www.railmoon.com
" Module: railmoon#widget#canvas
" Purpose: widget for drawing inside it
" -
" [ internal usage ]
" Name: callback_object
" Purpose: handler for base back calls
" -
let s:callback_object = {}
" -
" [ public library function ]
" Name: railmoon#widget#canvas#create
" Purpose: create "canvas" widget
" [ parameters ]
" name name of new vim window that will represent widget
" callback_object call back object with following methods
" on_draw() draw what inside canvas
" -
function! railmoon#widget#canvas#create(name, callback_object)
let new_object = railmoon#widget#base#create(a:name, s:canvas, [a:callback_object, s:callback_object])
call s:auto_command_setup()
return new_object
endfunction
" -
" [ internal usage ]
" Name: auto_command_setup
" Purpose: setup handlers for window triggers
" -
function! s:auto_command_setup()
" autocmd CursorMoved <buffer> call s:on_cursor_moved()
endfunction
function! s:callback_object.on_setup()
endfunction
" -
" [ internal usage ]
" Name: canvas
" Purpose: widget object "canvas"
" -
let s:canvas = {}
" -
" [ object method ]
" Object: canvas
" Name: draw
" Purpose: prepare_canvas for drawing and call user defined on_draw method
" -
function! s:canvas.draw()
call railmoon#trace#push('canvas.draw')
try
let selected = railmoon#widget#window#save_selected()
let is_selected = railmoon#widget#window#select(self.id)
if ! is_selected
throw 'widget:selection_window:draw:window_not_found'
endif
setlocal modifiable
0,$delete _
call railmoon#draw#prepare_canvas(winwidth('%'), winheight('%'))
call railmoon#widget#base#call_back(self, 'on_draw()')
setlocal nomodifiable
call railmoon#widget#window#load_selected(selected)
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction

View File

@@ -0,0 +1,207 @@
" Author: Mykola Golubyev ( Nickolay Golubev )
" Email: golubev.nikolay@gmail.com
" Home: www.railmoon.com
" Module: railmoon#widget#edit_line_window
" Purpose: provide window with callbacks for editing single line
let s:callback_object = {}
" -
" [ public library function ]
" Name: railmoon#widget#edit_line_window#create
" Purpose: create "edit line window" widget
" [ parameters ]
" name name of new vim window that will represent widget
" titlename name that will on title bar
" callback_object call back object with following methods
" on_normal_move
" on_insert_move
" on_type(character, is_alpha_numeric) : should return character to type
" -- and common handlers
" -
function! railmoon#widget#edit_line_window#create(name, titlename, callback_object)
let new_object = railmoon#widget#base#create(a:name, a:titlename, s:edit_line_window, s:callback_object, a:callback_object)
call railmoon#trace#debug('create edit line window:'.a:name)
" call railmoon#trace#debug(string(new_object))
setlocal modifiable
call s:auto_command_setup()
call s:insert_mode_key_typing_setup()
return new_object
endfunction
" -
" [ internal usage ]
" Name: edit_line_window
" Purpose: widget object "edit line window"
" -
let s:edit_line_window = {}
" -
" [ object method ]
" Object: edit_line_window
" Name: get_line
" Purpose: return entered line
" -
function! s:edit_line_window.get_line()
let selected = railmoon#widget#window#save_selected()
call self.select()
let text_line = getline(1)
call railmoon#widget#window#load_selected(selected)
return text_line
endfunction
" -
" [ object method ]
" Object: edit_line_window
" Name: set_line
" Purpose: setup text line to "edit line window"
" -
function! s:edit_line_window.set_line(line)
let selected = railmoon#widget#window#save_selected()
call self.select()
call setline(1, a:line)
call railmoon#widget#window#load_selected(selected)
endfunction
" -
" [ object method ]
" Object: edit_line_window
" Name: go_to_position
" Purpose: move cursor to specified position
" -
function! s:edit_line_window.go_to_position(position)
call self.select()
call cursor(1, a:position)
endfunction
" -
" [ object method ]
" Object: edit_line_window
" Name: go_to_end
" Purpose: move cursor to end
" -
function! s:edit_line_window.go_to_end()
call self.select()
call cursor(1, col('$'))
endfunction
" -
" [ object method ]
" Object: edit_line_window
" Name: go_to_start
" Purpose: move cursor to start of line
" -
function! s:edit_line_window.go_to_start()
call self.select()
call cursor(1, 1)
endfunction
" -
" [ internal usage ]
" Name: insert_mode_key_typing_setup
" Purpose: setup handlers for typing characters
" -
function! s:insert_mode_key_typing_setup()
for item in s:alpha_numeric_characters
execute 'inoremap <buffer> <silent> ' . item . ' <C-R>=<SID>on_insert_typing('''.item.''', 1)<CR>'
endfor
for item in s:not_alpha_numeric_characters
execute 'inoremap <buffer> <silent> ' . item . ' <C-R>=<SID>on_insert_typing('''.item.''', 0)<CR>'
endfor
endfunction
function! s:callback_object.on_setup()
call s:insert_mode_key_typing_setup()
endfunction
" -
" [ internal usage ]
" Name: on_insert_typing
" Purpose: handle typing
" -
function! s:on_insert_typing(character, is_alpha_numeric)
let callback_object = b:widget.callback_object
if has_key(callback_object, 'on_type')
return callback_object.on_type( a:character, a:is_alpha_numeric )
endif
return a:character
endfunction
" -
" [ internal usage ]
" Name: auto_command_setup
" Purpose: setup auto commands
" -
function! s:auto_command_setup()
autocmd CursorMoved <buffer> call s:on_cursor_moved(s:normal_mode)
autocmd CursorMovedI <buffer> call s:on_cursor_moved(s:insert_mode)
endfunction
" -
" [ internal usage ]
" Name: on_cursor_moved
" Purpose: handle cursor movement
" -
function! s:on_cursor_moved(mode)
if line('$') > 1
let new_line = join(getline(1, '$'), '')
2,$d
call setline(1, new_line)
call cursor(1, col('$'))
endif
let callback_object = w:widget.callback_object
if a:mode == s:normal_mode
call railmoon#widget#base#call_back(w:widget, 'on_normal_move')
else
call railmoon#widget#base#call_back(w:widget, 'on_insert_move')
endif
endfunction
" -
" [ internal usage ]
" Name: normal_mode
" Purpose: enumeration of mode
" -
let s:normal_mode = 0
" -
" [ internal usage ]
" Name: insert_mode
" Purpose: enumeration of mode
" -
let s:insert_mode = 1
" -
" [ internal usage ]
" Name: alpha_numeric_characters
" Purpose: store all typing characters
" -
let s:alpha_numeric_characters =
\ ['a','b','c','d','e','f','g','h','i','j','k','l','m',
\ 'n','o','p','q','r','s','t','u','v','w','x','y','z',
\ 'A','B','C','D','E','F','G','H','I','J','K','L','M',
\ 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
\ '0','1','2','3','4','5','6','7','8','9','<space>','_','=','"',':',';','.']
" -
" [ internal usage ]
" Name: not_alpha_numeric_characters
" Purpose: store not alpha numeric characters
" -
let s:not_alpha_numeric_characters =
\ ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '+', '-',
\ '{', '}', '[', ']', "'", '<', '>', ',', '?', '`', '~', '\', '\|']

View File

@@ -0,0 +1,408 @@
" Author: Mykola Golubyev ( Nickolay Golubev )
" Email: golubev.nikolay@gmail.com
" Site: www.railmoon.com
" Module: railmoon#widget#selection_window
" Purpose: provide window with ability to select elements
" -
" [ internal usage ]
" Name: callback_object
" Purpose: handler for base back calls
" -
let s:callback_object = {}
"
" elements for selection windows are dictionaries that have
" .data as list [] of text
" .header optional value that will be right aligned at left side of list
" -
" [ public library function ]
" Name: railmoon#widget#selection_window#create
" Purpose: create "selection window" widget
" [ parameters ]
" name name of new vim window that will represent widget
" titlename name that will on title bar
" callback_object call back object with following methods
" on_select(selected_line_text)
" on_close
" on_close_with_tab_page
" model model representation with following methods
" get_item(element)
" get_item_count()
" -
function! railmoon#widget#selection_window#create(name, titlename, selection_group, model, callback_object)
let new_object = railmoon#widget#base#create(a:name, a:titlename, s:selection_window, s:callback_object, a:callback_object)
call railmoon#trace#debug('create selection_window:'.a:name)
call railmoon#trace#debug(string(new_object))
let new_object.selected_item_number = 1
let new_object.selection_group = a:selection_group
let new_object.model = a:model
let new_object.yoffset = 0
let new_object.item_positions = []
" call new_object.draw_selection()
call s:auto_command_setup()
call s:key_mappings_setup()
return new_object
endfunction
" -
" [ internal usage ]
" Name: auto_command_setup
" Purpose: setup handlers for window triggers
" -
function! s:auto_command_setup()
autocmd CursorMoved <buffer> call s:on_cursor_moved()
endfunction
function! s:callback_object.on_setup()
call s:key_mappings_setup()
endfunction
" -
" [ internal usage ]
" Name: key_mappings_setup
" Purpose: setup key handlers for "selection window"
" -
function! s:key_mappings_setup()
nnoremap <buffer> <CR> :call <SID>on_select()<CR>
nnoremap <buffer> <2-LeftMouse> :call <SID>on_select()<CR>
endfunction
" -
" [ internal usage ]
" Name: on_select
" Purpose: handle item select command
" -
function! s:on_select()
let selected_item = w:widget.selected_item()
call railmoon#widget#base#call_back(w:widget, 'on_select', '"'.escape(string(selected_item),"\"'").'"')
endfunction
" -
" [ internal usage ]
" Name: on_cursor_moved
" Purpose: handle normal mode curor movement
" -
function! s:on_cursor_moved()
let line_number = line('.')
call w:widget.select_line(line_number)
endfunction
" -
" [ internal usage ]
" Name: selection_window
" Purpose: widget object "selection window"
" -
let s:selection_window = {}
" -
" [ internal usage ]
" Name: highlight_line
" Purpose: highlight line in selection window
" [ parameters ]
" line_number number of line to highlight
" group highlight group to use as highlight
" -
function! s:highlight_line(start, end, group)
let start = '"\%'.(a:start + 1).'l"'
let end = '"\%'.(a:end + 1).'l"'
let id = w:widget_id
let syn_command = 'syn region selection_window_selected_line'.id.' start='.start.' end = '.end.' contains=Search'
let hi_link_command = 'hi link selection_window_selected_line'.id.' '.a:group
exec syn_command
exec hi_link_command
endfunction
" -
" [ internal usage ]
" Name: clear_highlight_line
" Purpose: remove highlight line in selection window
" -
function! s:clear_highlight_line()
let id = w:widget_id
try
exec 'syntax clear selection_window_selected_line'.id
catch /.*/
endtry
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: draw
" Purpose: append all lines to buffer while remove old ones
" -
function! s:selection_window.draw()
call railmoon#trace#push('selection_window.draw')
try
let selected = railmoon#widget#window#save_selected()
let is_selected = railmoon#widget#window#select(self.id)
if ! is_selected
throw 'widget:selection_window:draw:window_not_found'
endif
setlocal modifiable
0,$delete _
let y = 0
let i = 0
let item_count = self.model.get_item_count()
let item_size = len(self.model.get_item(0).data)
let header_max_lenght = 0
let self.item_positions = []
let items_to_draw = []
" gathrer visual items on window
" determine max header length
"
while y <= ( winheight('%') - item_size ) && ( i < item_count )
let item = self.model.get_item(i)
let item_header_len = len(item.header)
if item_header_len > header_max_lenght
let header_max_lenght = item_header_len
endif
call add(items_to_draw, item)
let item_size = len(item.data)
call add( self.item_positions, [ y, y + item_size ] )
let y += item_size
let i += 1
endwhile
let is_no_headers = header_max_lenght == 0
" highlight headers if any
"
let window_id = w:widget_id
try
exec 'syntax clear selection_window_lines_header'.window_id
catch /.*/
endtry
if ! is_no_headers
exec 'syntax match selection_window_lines_header'.window_id.' "^[^|]\+|"'
endif
try
exec 'hi link selection_window_lines_header'.window_id.' String'
catch /.*/
endtry
let lines = []
" build lines to append to buffer
"
for item in items_to_draw
let item_header = item.header
let is_header_present = len(item_header) > 0
if is_header_present
call add(lines, printf(' %-'.header_max_lenght.'s | ', item_header).item.data[0])
elseif is_no_headers
call add(lines, ' '.item.data[0])
else
call add(lines, printf(' %'.header_max_lenght.'s ', item_header).item.data[0])
endif
for line in item.data[1:]
if is_header_present
call add(lines, printf(' %-'.header_max_lenght.'s | ', '').line)
elseif is_no_headers
call add(lines, ' '.line)
else
call add(lines, printf(' %'.header_max_lenght.'s ', '').line)
endif
endfor
endfor
let win_width = winwidth('%')
let wide_lines = []
for line in lines
let diff = win_width - len(line)
let new_line = line
if diff > 0
let new_line = line . printf('%'.diff.'s', ' ')
endif
call add(wide_lines, new_line)
endfor
call setline(1, wide_lines)
call self.draw_selection()
setlocal nomodifiable
call railmoon#widget#window#load_selected(selected)
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: draw_selection
" Purpose: show selection in selection window
" -
function! s:selection_window.draw_selection()
call railmoon#trace#push('selection_window.draw_selection')
call railmoon#trace#debug('id = '.self.id)
try
let selected = railmoon#widget#window#save_selected()
call self.select()
if len(self.item_positions) > 0
let start_line_number_in_window = self.item_positions[ self.selected_item_number - 1 ][0]
let end_line_number_in_window = self.item_positions[ self.selected_item_number - 1 ][1]
exec start_line_number_in_window
call s:clear_highlight_line()
call s:highlight_line(start_line_number_in_window, end_line_number_in_window, self.selection_group)
endif
call railmoon#widget#window#load_selected(selected)
finally
call railmoon#trace#pop()
endtry
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: scrool_to
" Purpose: scrool window to show given line as first line
" [ parameters ]
" line_number line to show first in window
" -
function! s:selection_window.scrool_to(line_number)
let self.yoffset = a:line_number
call self.draw()
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: selection_down
" Purpose: select next item
" [ parameters ]
" cycle cycle or not movement
" -
function! s:selection_window.selection_down(cycle)
let last_item_number_on_window = len(self.item_positions)
if self.selected_item_number >= last_item_number_on_window
if ! a:cycle
return
else
let self.selected_item_number = 1
endif
else
let self.selected_item_number += 1
endif
call self.draw_selection()
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: selection_up
" Purpose: select previous item
" [ parameters ]
" cycle cycle or not movement
" -
function! s:selection_window.selection_up(cycle)
let last_item_number_on_window = len(self.item_positions)
if self.selected_item_number <= 1
if ! a:cycle
return
else
let self.selected_item_number = last_item_number_on_window
endif
else
let self.selected_item_number -= 1
endif
call self.draw_selection()
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: select_line
" Purpose: select pointed line
" [ parameters ]
" line_number number of line to select
" -
function! s:selection_window.select_line(line_number)
let item_count = self.model.get_item_count()
let i = 0
for region in self.item_positions
if a:line_number >= region[0] && a:line_number <= region[1]
let self.selected_item_number = i + 1
break
endif
let i+=1
endfor
call self.draw_selection()
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: select_item
" Purpose: select pointed item by number
" [ parameters ]
" item_number number of item to select
" -
function! s:selection_window.select_item(item_number)
let self.selected_item_number = a:item_number
call self.draw_selection()
endfunction
" -
" [ object method ]
" Object: selection_window
" Name: selected_item
" Purpose: return selected item text
" -
function! s:selection_window.selected_item()
let item = self.model.get_item(self.selected_item_number - 1)
return item
endfunction

View File

@@ -0,0 +1,167 @@
" Author: Mykola Golubyev ( Nickolay Golubev )
" Email: golubev.nikolay@gmail.com
" Home: www.railmoon.com
" Module: railmoon#widget#window
" Purpose: util functions for work with widget windows id
"
" -
" [ public library function ]
" Name: railmoon#widget#window#find_on_tab
" Purpose: determine window number on given tab with pointed id
" [ parameters ]
" tabpage_number number of tabpage
" variable_name name of window id variable
" id window id to search
" -
function! railmoon#widget#window#find_on_tab(tabpage_number, variable_name, id)
let windows_count = tabpagewinnr(a:tabpage_number, '$')
let window_number = 1
while window_number <= windows_count
let window_id = gettabwinvar(a:tabpage_number, window_number, a:variable_name)
if a:id == window_id
return window_number
endif
let window_number += 1
endwhile
return 0
endfunction
" -
" [ public library function ]
" Name: railmoon#widget#window#find
" Purpose: determine tabpage number and window number as list of two elements with pointed id
" [ parameters ]
" id widget id to search
" -
function! railmoon#widget#window#find(id)
let tabpage_count = tabpagenr('$')
let tabpage_number = 1
while tabpage_number <= tabpage_count
let window_number = railmoon#widget#window#find_on_tab(tabpage_number, 'widget_id', a:id)
if window_number
return [ tabpage_number, window_number ]
endif
let tabpage_number += 1
endwhile
throw 'window with "widget_id" = '.a:id.' not found'
return [0, 0]
endfunction
" -
" [ public library function ]
" Name: railmoon#widget#window#visible
" Purpose: determine visible or not widget window with pointed id
" [ parameters ]
" id widget id to select
" -
function! railmoon#widget#window#visible(id)
if exists('w:widget_id') && w:widget_id == a:id
return 1
endif
let window_number = railmoon#widget#window#find_on_tab(tabpagenr(), 'widget_id', a:id)
return window_number > 0
endfunction
" -
" [ public library function ]
" Name: railmoon#widget#window#select
" Purpose: make window with given widget id active
" [ parameters ]
" id widget id to select
" -
function! railmoon#widget#window#select(id)
call railmoon#trace#push('window#select')
call railmoon#trace#debug('id = '.a:id)
try
if exists('w:widget_id') && w:widget_id == a:id
return 1
endif
let tabpage_and_window_number = railmoon#widget#window#find(a:id)
if tabpage_and_window_number[0] == 0
return 0
endif
call s:select_window(tabpage_and_window_number[0], tabpage_and_window_number[1])
return 1
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ public library function ]
" Name: railmoon#widget#window#save_selected
" Purpose: save current tabpage number, window mark id, position, mode
" -
function! railmoon#widget#window#save_selected()
call railmoon#trace#push('window#save_selected')
try
if ! exists('w:railmoon_window_mark_id')
let w:railmoon_window_mark_id = railmoon#id#acquire('railmoon_window_mark_id')
endif
return [tabpagenr(), w:railmoon_window_mark_id, getpos('.'), mode()]
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ public library function ]
" Name: railmoon#widget#window#load_selected
" Purpose: select tabpage number, window number, position, mode
" [ parameters ]
" selection list with four elements: tabpage number, window mark id,
" position, mode
" -
function! railmoon#widget#window#load_selected(selection)
call railmoon#trace#push('window#load_selected')
try
exec a:selection[0].'tabnext'
let window_number =
\ railmoon#widget#window#find_on_tab(a:selection[0],
\ 'railmoon_window_mark_id',
\ a:selection[1])
exec window_number.'wincmd w'
if a:selection[3] == 'n'
stopinsert
elseif a:selection[3] == 'i'
startinsert
endif
call setpos('.', a:selection[2])
finally
call railmoon#trace#debug('...')
call railmoon#trace#pop()
endtry
endfunction
" -
" [ internal usage ]
" Purpose: open tabpage number and select window number
" -
function! s:select_window(tabpage_number, window_number)
exec a:tabpage_number . 'tabnext'
exec a:window_number.'wincmd w'
endfunction