vimのプレゼンツールその2

vimのプレゼンツールで作ったのをちょっと直した。

やったこと

  • 前回は各スライドを一気に表示していたが、h, lではページタイトルのみ表示するように変更
  • j, kで各行を順番に表示したり消したりできるようにした
  • カーソル行を強調表示するようにした

動作イメージ


ソース

" Presentation Object
let s:Presentation = { 'slides' : [], 'current' : 0, 'currentLine' : 0 }

function! s:Presentation.load()
  let self.slides = [
        \ {
        \   'title' : 'presentation.vimについて',
        \   'contents' : [
        \     '* 概要',
        \     '* 起動方法',
        \     '* 使い方',
        \     '* 今後の予定',
        \   ]
        \ },
        \ {
        \   'title' : '概要',
        \   'contents' : [
        \     '* vimでプレゼンするためのスクリプト',
        \     '* はっきりいって自己満足です。本当にありg(ry',
        \   ]
        \ },
        \ {
        \   'title' : '起動方法',
        \   'contents' : [
        \     '* 任意の空バッファ上で:source presentation.vim',
        \     '* :PresentationEnable でプレゼンモード開始',
        \     '* :PresentationDisable でプレゼンモード終了',
        \   ]
        \ },
        \ {
        \   'title' : '使い方',
        \   'contents' : [
        \     '* l で次のスライドを表示',
        \     '* h で前のスライドを表示',
        \     '* j で次の行へ進める',
        \     '* k で前の行へ戻る',
        \   ]
        \ },
        \ {
        \   'title' : '今後の予定',
        \   'contents' : [
        \     '* スライドの中身は外部化するかも。',
        \     '* ページ全体や、各行ごとにhighlightを切り替え可能にするかも。',
        \   ]
        \ },]
  let self.current = 0
  let self.currentLine = 0
endfunction

" カレントスライドのタイトルを表示
function! s:Presentation.showPageTitle()
  execute 'normal o '
  call setpos('.', [0, winline(), 1, winwidth(0)/5])
  execute 'normal i ' . self.currentSlide()['title']
  execute 'normal o '
endfunction

" カレントスライドの現在行を表示
function! s:Presentation.showPageContentsLine()
    execute 'normal o '
    call setpos('.', [0, winline(), 1, winwidth(0)/6])
    execute 'normal i ' . self.currentSlide()['contents'][self.currentLine]
endfunction

" カレントスライドを返す
function! s:Presentation.currentSlide()
  return self.slides[self.current]
endfunction

" カレントスライドをクリアする
function! s:Presentation.clearPage()
  execute 'normal ggdG'
  let self.currentLine = 0
endfunction

" カレントスライドの現在行をクリアする
function! s:Presentation.clearPageContentsLine()
  execute 'normal dd'
endfunction

function! s:Presentation.showNextPage()
  let nextIndex = self.current + 1
  if nextIndex == len(self.slides)
    echo '最後のページです'
    return
  endif
  call self.clearPage()
  let self.current = nextIndex
  call self.showPageTitle()
endfunction

function! s:Presentation.showPrevPage()
  let prevIndex = self.current - 1
  if prevIndex < 0
    echo '最初のページです'
    return
  endif
  call self.clearPage()
  let self.current = prevIndex
  call self.showPageTitle()
endfunction

function! s:Presentation.showNextLine()
  let nextIndex = self.currentLine + 1
  if nextIndex > len(self.currentSlide()['contents'])
    " TODO 次ページに飛ぶようにすべき?
    return
  endif
  call self.showPageContentsLine()
  let self.currentLine = nextIndex
endfunction

function! s:Presentation.showPrevLine()
  let prevIndex = self.currentLine - 1
  if prevIndex < 0
    " TODO 前ページに飛ぶようにすべき?
    return
  endif
  call self.clearPageContentsLine()
  let self.currentLine = prevIndex
endfunction

" スクリプトローカルの関数定義
" 次ページを表示
function! s:ShowNextPage()
  call s:Presentation.showNextPage()
endfunction

" 前ページを表示
function! s:ShowPrevPage()
  call s:Presentation.showPrevPage()
endfunction

" カレントスライドの次の行を表示
function! s:ShowNextLine()
  call s:Presentation.showNextLine()
endfunction

" カレントスライドの前の行を表示
function! s:ShowPrevLine()
  call s:Presentation.showPrevLine()
endfunction

" プレゼンテーションを有効化する
function! s:Enable()
  set paste
  set ve=all
  set laststatus=0
  set cursorline
  highlight CursorLine ctermfg=184

  map <buffer> <silent> j :call <SID>ShowNextLine()<CR>
  map <buffer> <silent> k :call <SID>ShowPrevLine()<CR>
  map <buffer> <silent> h :call <SID>ShowPrevPage()<CR>
  map <buffer> <silent> l :call <SID>ShowNextPage()<CR>

  call s:Presentation.clearPage()
  call s:Presentation.load()
  call s:Presentation.showPageTitle()
endfunction

" プレゼンテーションを無効化する
function! s:Disable()
  set nopaste
  set ve=
  set laststatus=2
  set nocursorline
  highlight clear CursorLine
  " TODO mapの定義も解除すべき?bufferローカルだから別にいいかなと思うけど。
endfunction

" コマンドの定義
command! -bar -narg=0 PresentationEnable  call s:Enable()
command! -bar -narg=0 PresentationDisable  call s:Disable()