Tvorba pluginů pro Vim s využitím programovacího jazyka Lua

Pavel Tišnovský 5. 1. 2016

Textový editor Vim je oblíbený mj. i díky dostupnosti velkého množství pluginů (přídavných modulů). Tyto pluginy lze vytvářet ve Vim Scriptu, což je skriptovací jazyk, který je přímo součástí Vimu. Ovšem pro složitější a rozsáhlejší pluginy se používají i další skriptovací jazyky, mezi něž se zařadila i Lua.

Obsah

1. Tvorba pluginů pro Vim s využitím programovacího jazyka Lua

2. Interaktivní test, zda Vim obsahuje konektor pro zvolený programovací jazyk

3. Test existence rozhraní pro vybraný skriptovací jazyk přímo ve Vim Scriptu

4. Základní rozhraní pro využití programovacího jazyka Lua

5. Příkaz luafile

6. Příkaz luado

7. Modul vim využitelný z programovacího jazyka Lua

8. Praktický příklad: přepis promítačky slajdů z Vim Scriptu do jazyka Lua

9. Repositář s demonstračními příklady

10. Odkazy na Internetu

1. Tvorba pluginů pro Vim s využitím programovacího jazyka Lua

V seriálu o textovém editoru Vim jsme se již seznámili s některými způsoby tvorby pluginů (přídavných modulů) pro tento textový editor. Připomeňme si, že primárním programovacím jazykem pro tvorbu jednoduchých několikařádkových pomocných nástrojů ale i rozsáhlých pluginů je stále interní skriptovací jazyk nazývaný Vim script, vimscript či pouze viml. Tento imperativní programovací jazyk je přímo součástí samotného textového editoru, což lze samozřejmě považovat za výhodu (ostatně i samotné konfigurační soubory jsou psané v tomto jazyce). Díky tomu, že Vim script je zabudován přímo do Vimu, mohou uživatelské skripty využívat přístup jak ke všem globálním i lokálním konfiguračním parametrům Vimu, tak i k obsahu jednotlivých bufferů, které samozřejmě mohou být těmito skripty modifikovány (mnoho skriptů taktéž využívá vlastní buffery se speciálním obsahem, příkladem mohou být například pluginy histwin či undotree, které ve speciálních bufferech zobrazují historii editace dokumentů.

Obrázek 1: Příklad pluginu, který používá vlastní buffer pro zobrazení svého (textového) uživatelského rozhraní – takto vypadá okno pluginu nazvaného „histwin“ ve chvíli, kdy se již k bufferu zaznamenalo několik operací.

I přes poměrně rozsáhlé možnosti, které programovací jazyk Vim Script uživatelům textového editoru Vim i programátorům poskytuje, by však v některých případech mohlo být výhodnější použít některý obecný skriptovací jazyk. Může se jednat o ty případy, kdy je zapotřebí volat nějakou funkci dostupnou z externí knihovny, volat již hotový (mnohdy i velmi složitý) skript, analyzovat právě editovaný program s využitím reflexe, nebo pouze to, že je programátor na daný jazyk prostě navyklý, má pro něj vhodné vývojové a ladicí nástroje atd. Zatímco v konkurenčním editoru Emacs jsou tvůrci pluginů vedeni k použití Elispu, ve Vimu je tomu jinak – komu z nějakých důvodů nevyhovuje VimScript, může použít rozhraní (konektor) pro některý jiný skriptovací jazyk, mezi něž patří zejména Perl, Python, Ruby, které jsou doplněny o TCL a Scheme (přesněji řečeno mzscheme a.k.a. Racket) a nověji taktéž o programovací jazyk Lua.

Obrázek 2: Další plugin s vlastním uživatelským rozhraním tvořeným pomocí skriptu: undotree.

2. Interaktivní test, zda Vim obsahuje konektor pro zvolený programovací jazyk

Před využitím skriptů napsaných v některém potenciálně podporovaném programovacím jazyce je nejprve vhodné zjistit, zda vámi používaná verze Vimu skutečně obsahuje příslušná rozhraní (konektor). Možností, jak zjistit existenci těchto rozhraní, existuje více. Interaktivně je možné požadovanou informaci nejjednodušeji zjistit s využitím příkazu:

:version

Obrázek 3: Ukázka minimalisticky pojaté varianty Vimu: na výpisu podporovaných a nepodporovaných vlastností Vimu je patrné, že šestnáctibitová DOSová varianta tohoto textového editoru má mnohá omezení, která vycházejí především z toho, že se celý editor i editované soubory (+ historie operací) musí vejít do necelých 640kB RAM.

Po spuštění tohoto příkazu se na obrazovku vypíše seznam vlastností Vimu, přičemž u každé vlastnosti je s využitím znaků + a - naznačeno, zda je tato vlastnost podporována či nikoli. Ukažme si, jak vypadá výpis pro variantu Vimu s podporou některých skriptovacích jazyků (nikoli však všech jazyků, což je z výpisu taktéž patrné). Konkrétně se jedná o stařičký Vim nainstalovaný z balíčku vim-enhanced-7.2.148–1 pro Fedoru (zajímají nás jen podtržené vlastnosti, bohužel tato starší verze Vimu ještě nedokázala vlastnosti seřadit do přehledných sloupců):

:ver
VIM - Vi IMproved 7.2 (2008 Aug 9, compiled Mar 27 2009 08:42:32)
Included patches: 1-148
Modified by <bugzilla@redhat.com>
Compiled by <bugzilla@redhat.com>
Huge version without GUI.  Features included (+) or not (-):
+arabic +autocmd -balloon_eval -browse ++builtin_terms +byte_offset +cindent
-clientserver -clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments
+cryptv +cscope +cursorshape +dialog_con +diff +digraphs -dnd -ebcdic
+emacs_tags +eval +ex_extra +extra_search +farsi +file_in_path +find_in_path
+float +folding -footer +fork() +gettext -hangul_input +iconv +insert_expand
+jumplist +keymap +langmap +libcall +linebreak +lispindent +listcmds +localmap
+menu +mksession +modify_fname +mouse -mouseshape +mouse_dec +mouse_gpm
-mouse_jsbterm +mouse_netterm -mouse_sysmouse +mouse_xterm +multi_byte
+multi_lang -mzscheme -netbeans_intg -osfiletype +path_extra +perl +postscript
+printer +profile +python +quickfix +reltime +rightleft -ruby +scrollbind
+signs +smartindent -sniff +statusline -sun_workshop +syntax +tag_binary
+tag_old_static -tag_any_white -tcl +terminfo +termresponse +textobjects +title
 -toolbar +user_commands +vertsplit +virtualedit +visual +visualextra +viminfo
+vreplace +wildignore +wildmenu +windows +writebackup -X11 -xfontset -xim -xsmp
 -xterm_clipboard -xterm_save
   system vimrc file: "/etc/vimrc"
     user vimrc file: "$HOME/.vimrc"
      user exrc file: "$HOME/.exrc"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H     -O2 -g -pipe -Wall -Wp,-D_FO
RTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -ma
rch=i386 -mtune=generic -fasynchronous-unwind-tables -D_GNU_SOURCE -D_FILE_OFFSE
T_BITS=64 -D_FORTIFY_SOURCE=2 -D_FORTIFY_SOURCE=1    -D_REENTRANT -D_GNU_SOURCE
-DDEBUGGING  -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/
usr/include/gdbm  -I/usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE  -I/usr/i
nclude/python2.5 -pthread
Linking: gcc   -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.10.0/i386-linux-thread-multi/C
ORE   -L/usr/local/lib -o vim       -lselinux  -lncurses -lacl -lgpm   -Wl,-E -W
l,-rpath,/usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE  -L/usr/local/lib  -
L/usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE -lperl -lresolv -lutil -lc -
L/usr/lib/python2.5/config -lpython2.5 -lutil -lm -Xlinker -export-dynamic

Novější verze Vimu již umí vlastnosti vypsat přehledněji do sloupců (počet sloupců závisí na šířce okna editoru):

VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Jan  2 2014 19:39:59)
Included patches: 1-52
Modified by pkg-vim-maintainers@lists.alioth.debian.org
Compiled by buildd@
Huge version with GTK2 GUI.  Features included (+) or not (-):
+acl             +farsi           +mouse_netterm   +syntax
+arabic          +file_in_path    +mouse_sgr       +tag_binary
+autocmd         +find_in_path    -mouse_sysmouse  +tag_old_static
+balloon_eval    +float           +mouse_urxvt     -tag_any_white
+browse          +folding         +mouse_xterm     +tcl
++builtin_terms  -footer          +multi_byte      +terminfo
+byte_offset     +fork()          +multi_lang      +termresponse
+cindent         +gettext         -mzscheme        +textobjects
+clientserver    -hangul_input    +netbeans_intg   +title
+clipboard       +iconv           +path_extra      +toolbar
+cmdline_compl   +insert_expand   +perl            +user_commands
+cmdline_hist    +jumplist        +persistent_undo +vertsplit
+cmdline_info    +keymap          +postscript      +virtualedit
+comments        +langmap         +printer         +visual
+conceal         +libcall         +profile         +visualextra
+cryptv          +linebreak       +python          +viminfo
+cscope          +lispindent      -python3         +vreplace
+cursorbind      +listcmds        +quickfix        +wildignore
+cursorshape     +localmap        +reltime         +wildmenu
+dialog_con_gui  +lua             +rightleft       +windows
+diff            +menu            +ruby            +writebackup
+digraphs        +mksession       +scrollbind      +X11
+dnd             +modify_fname    +signs           -xfontset
-ebcdic          +mouse           +smartindent     +xim
+emacs_tags      +mouseshape      -sniff           +xsmp_interact
+eval            +mouse_dec       +startuptime     +xterm_clipboard
+ex_extra        +mouse_gpm       +statusline      -xterm_save
+extra_search    -mouse_jsbterm   -sun_workshop    +xpm

Poznámka: povšimněte si, že se zde již rozlišuje mezi Pythonem 2 a Pythonem 3, což je samozřejmě pro tvůrce pluginů důležité.

Obrázek 4: Dostupnost či naopak nedostupnost konektorů k některým programovacím jazykům v moderní verzi Vimu.

Obrázek 5: Stejná verze Vimu, jako na předchozím screenshotu, ovšem zkompilovaná pouze s minimální množinou vlastností.

3. Test existence rozhraní pro vybraný skriptovací jazyk přímo ve Vim Scriptu

V mnoha praktických případech je však nutné zjistit podporu rozhraní pro vybraný programovací jazyk přímo ve skriptu (zde je myšlen Vim Script a.k.a. viml, tj. interní skriptovací jazyk Vimu). Pro tento účel lze využít funkci nazvanou has, které se ve formě řetězce předá jméno testované vlastnosti, tj. provede se toto volání:

has("vlastnost")

Funkce has vrací numerickou hodnotu 0 nebo 1 v závislosti na tom, zda je vlastnost předaná funkci has() ve formě řetězce ve Vimu podporována či nikoli (u jména vlastnosti se ignoruje velikost písmen, což znamená, že například řetězec „Lua“, „lua“, „LUA“ či dokonce „lUA“ označuje shodnou vlastnost). Informace pro příkaz :version a hodnoty vrácené funkcí has() jsou zjišťovány ze stejné interní struktury Vimu, proto jsou konzistentní. Můžete si ostatně sami vyzkoušet, která rozhraní ke skriptovacím jazykům jsou ve vaší variantě Vimu aktuálně podporována.

Zjištění existence rozhraní pro programovací jazyk Python:

:echo has("Python")
1

Zjištění existence rozhraní pro programovací jazyk Python 3:

:echo has("Python3")
0

Zjištění existence rozhraní pro programovací jazyk Perl:

:echo has("Perl")
1

Zjištění existence rozhraní pro programovací jazyk Ruby:

:echo has("Ruby")
0

Zjištění existence rozhraní pro programovací jazyk Tcl:

:echo has("Tcl")
0

Zjištění existence rozhraní pro programovací jazyk Scheme:

:echo has("mzscheme")
0

A pro nás dnes nejdůležitější test existence rozhraní pro programovací jazyk Lua:

:echo has("lua")
1

Vzhledem k tomu, že se ve Vim Scriptu používají pro reprezentaci pravdivostních hodnot namísto konstant true/false právě číselné hodnoty 0 a 1 (podobně jako v céčku), je možné funkci has() vložit přímo do podmíněného příkazu:

:if has("Python")
:  python print 6*7
:endif

Popř. s chybovým hlášením:

:if has("Python")
:  python print 6*7
:else
:  echo "Rozhraní pro Python není podporováno"
:endif

Dtto pro programovací jazyk Perl:

:if has("Perl")
:  perldo $_=reverse($_);
:endif
:if has("Perl")
:  perldo $_=reverse($_);
:else
:  echo "Rozhraní pro Perl není podporováno"
:endif

Či pro programovací jazyk Lua:

:if has("Lua")
:  lua local x = 6*7
:  lua print(x)
:else
:  echo "Rozhraní pro Perl není podporováno"
:endif

Následující skript naprogramovaný přímo ve Vim Scriptu po svém spuštění příkazem:

:source lang_test.vim

či pouze:

:so lang_test.vim

vypíše informace o podporovaných i nepodporovaných konektorech na vybrané programovací jazyky:

function! SupportForLanguage(languageName)
    echo "Support for language " . a:languageName . ":"
    if has(a:languageName)
        echo "provided"
    else
        echo "absent"
    end
endfunction
 
let s:langs=["Python", "Python3", "Perl", "Tcl", "mzscheme", "Lua", "Ruby"]
 
for lang in s:langs
    call SupportForLanguage(lang)
endfor

Poznámka: povšimněte si, jak může být psaní nástrojů ve Vim Scriptu komplikované; týká se to například nutnosti mít na začátku funkcí velké písmeno nebo prefix s:, argumenty funkcí musí mít prefix a:, proměnné lokální v rámci modulu taktéž prefix s:, globální proměnné prefix g: atd.

Obrázek 6: Výsledek běhu skriptu pro zjištění informací o podporovaných i nepodporovaných konektorech na vybrané programovací jazyky.

4. Základní rozhraní pro využití programovacího jazyka Lua

Pokud je do aktuální (vámi používané) verze textového editoru Vim zařazen i konektor pro programovací jazyk Lua, je možné přímo z editoru či z libovolného skriptu zavolat jeden příkaz napsaný v Lue či dokonce sérii příkazů. Přitom je zachován kontext, což například znamená, že globální proměnné v jazyku Lua jsou zapamatovány, stejně tak deklarace funkcí atd. Základním příkazem sloužícím pro spuštění či vyhodnocení libovolného příkazu nebo výrazu napsaného v programovacím jazyku Lua, je příkaz lua zapisovaný v příkazovém režimu. Ostatně funkci tohoto příkazu si můžeme velmi snadno otestovat.

V příkazovém režimu:

:lua x = 6
:lua y = 7
:lua print("The Answer to the Ultimate Question of Life, the Universe, and Everything: " .. x*y)

Ve skriptu (viz též zdrojový kód tohoto skriptu, spustíte ho příkazem :so script1.vim):

lua x = 6
lua y = 7
lua print("The Answer to the Ultimate Question of Life, the Universe, and Everything: " .. x*y)

Jak je však již z tohoto příkladu patrné, není tento způsob vhodný pro zápis delších (víceřádkových) sekvencí kódu. V tomto případě je výhodnější využít druhého způsobu, který se podobá použití takzvaných here documents v shellu, Pythonu, Ruby, Perlu, PHP i v některých dalších skriptovacích jazycích. Za příkazem lua se použije dvojice znaků << následovaná symbolem, který ohraničuje tu část skriptu, která je naprogramována v jazyku Lua (celý skript):

lua << EOF
local x = 6
local y = 7
print("The Answer to the Ultimate Question of Life, the Universe, and Everything: " .. x*y)
EOF

Alternativně je možné vynechat symbol ohraničující část Lua skriptu. V tomto případě musí být tato část oddělena znakem tečka uvedeným na začátku řádku:

lua <<
local x = 6
local y = 7
print("The Answer to the Ultimate Question of Life, the Universe, and Everything: " .. x*y)
.
" ^ tecka na zacatku predchoziho radku

Pozor ovšem na to, aby tečka byla skutečně umístěna na začátku řádku, protože tento skript je chybný, ovšem chybové hlášení je poněkud kryptické:

lua <<
local x = 6
local y = 7
print("The Answer to the Ultimate Question of Life, the Universe, and Everything: " .. x*y)
  .
" ^ tecka musi byt umistena na zacatku radku

Obrázek 7: Pokud není tečka ukončující část Lua skriptu umístěna na začátku řádku, vypíše Vim (ve spolupráci s interpretrem jazyka Lua) toto kryptické chybové hlášení.

5. Příkaz luafile

Z popisu uvedeného v předchozí kapitole vyplývá, že jedna z možností, jak vytvořit delší plugin napsaný kompletně v jazyku Lua, spočívá v tom, že se tento skript uloží do zdrojového souboru s koncovkou .vim, na jeho začátku se uvede řádek lua << a na samotném konci pak samostatná tečka. To je ovšem poměrně nevýhodné, protože mnoho textových editorů (včetně Vimu) bude špatně rozeznávat typ souborů atd. Výhodnější by bylo z Vimu volat skript napsaný kompletně v jazyku Lua, tj. bez prvního a posledního „speciálního řádku“. To je samozřejmě taktéž možné, a to konkrétně příkazem :luafile, který se podobá příkazu :source, ovšem skript je interpretován přímo jazykem Lua a nikoli Vimem. Příkladem může být následující skript, který pracuje stejně jako oba skripty předchozí, ovšem současně se jedná o syntakticky bezchybný program v Lue:

-- This script does not use lua << etc.
 
local x = 6
local y = 7
print("The Answer to the Ultimate Question of Life, the Universe, and Everything: " .. x*y)

Tento skript se snadno spustí příkazem:

:luafile script5.lua

6. Příkaz luado

Velmi zajímavým příkazem, který může být v mnoha pluginech dobře využitelný, je příkaz :luado. Před tímto příkazem je možné uvést rozsah řádků, podobně jako u běžných vimovských příkazů typu :w apod. V případě, že rozsah není uveden, uvažuje se, že je vybrán celý buffer, tj. implicitně se použije rozsah % nebo 1,$. Za :luado se uvádí libovolný příkaz jazyka Lua, který je automaticky a postupně (iterativně) spuštěn pro všechny řádky/vybrané řádky v aktivním bufferu. Jinými slovy to znamená, že pokud není explicitně uveden rozsah platnosti, je příkaz v implicitní programové smyčce aplikován na každý textový řádek, jenž se nachází v aktivním bufferu, počínaje prvním řádkem. Obsah tohoto řádku je vždy umístěn do proměnné line, číslo řádku pak do proměnné linenr.

Ukažme si jednoduchý příklad, který pro každý vybraný řádek (či všechny řádky) aktivního bufferu vypíše jejich číslo a délku:

:luado print(linenr .. " -> " .. string.len(line))

Zajímavé je, že pokud funkce volaná příkazem luado má nějakou návratovou hodnotu, je aktuální (právě zpracovávaný řádek) touto hodnotou ovlivněn. Potřebujete tedy řádky očíslovat? Žádný problém:

:luado return linenr .. " " .. line

Poznámka: i když je možné pomocí :luado měnit obsah všech řádků v aktivním bufferu, nelze s jeho využitím textové řádky do bufferu přidávat ani je mazat. Pro takovou činnost je nutné použít techniky popsané příště.

7. Modul vim využitelný z programovacího jazyka Lua

Skripty vytvořené v jazyce Lua mohou používat všechny základní knihovny tohoto jazyka, tj. například včetně knihovny io atd. Ovšem navíc je možné použít ještě jeden speciální modul nazvaný vim, který programátorům nabízí API k Vimu. V následující tabulce jsou vypsány některé funkce, které tento modul programátorům nabízí. Bližší popis těchto funkcí bude – samozřejmě společně s demonstračními příklady – uveden příště:

# Funkce Význam
1 vim.command(příkaz) spustí libovolný příkaz Vimu přímo z Lua skriptu
2 vim.eval(výraz) vyhodnotí libovolný vimovský příkaz přímo z Lua skriptu
3 vim.open(jméno_souboru) otevře nový buffer
4 vim.line() vrátí obsah aktuálního textového řádku v aktivním bufferu (jako řetězec)

8. Praktický příklad: přepis promítačky slajdů z Vim Scriptu do jazyka Lua

S jednoduchou verzí skriptu určeného pro prohlížení slajdů jsme se již v tomto seriálu setkali, takže se podívejme na způsob konverze tohoto prográmku z Vim Scriptu do programovacího jazyka Lua. Budeme převádět následující (velmi jednoduchou) variantu skriptu:

" Slideshow tool v1.1
" Pavel Tisnovsky 2012, 2013, 2014
 
 
 
" Seznam s nazvy slajdu
let g:slides=readfile("list.txt")
 
" Prvky v poli se cisluji od nuly!
let g:index=0
 
function! GotoFirstSlide()
    let g:index = 0
endfunction
 
function! GotoLastSlide()
    let g:index = len(g:slides) - 1
endfunction
 
function! BeforeFirstSlide()
    return g:index < 0
endfunction
 
function! AfterLastSlide()
    return g:index >= len(g:slides)
endfunction
 
function! ShowNextSlide()
    let g:index += 1
    if AfterLastSlide()
        call GotoFirstSlide()
    endif
    call ShowActualSlide()
endfunction
 
function! ShowPrevSlide()
    let g:index -= 1
    if BeforeFirstSlide()
        call GotoLastSlide()
    endif
    call ShowActualSlide()
endfunction
 
function! ShowFirstSlide()
    call GotoFirstSlide()
    call ShowActualSlide()
endfunction
 
function! ShowLastSlide()
    call GotoLastSlide()
    call ShowActualSlide()
endfunction
 
function! ShowActualSlide()
    execute "edit" g:slides[g:index]
endfunction
 
function! StatusLine()
    return "Slide " . (1+g:index) . "/" . len(g:slides) . " : " . g:slides[g:index]
endfunction
 
" Hot keys
map <PageUp>   :call ShowPrevSlide()<cr>
map <PageDown> :call ShowNextSlide()<cr>
map <Home>     :call ShowFirstSlide()<cr>
map <End>      :call ShowLastSlide()<cr>
 
" Setup
set statusline=%!StatusLine()
 
" Potrebujeme zobrazit stavovy radek i ve chvili,
" kdy je zobrazeno pouze jedno okno
set laststatus=2
 
" Spustit prezentaci
:call ShowFirstSlide()

Při převodu se budeme řídit následujícími body:

  1. Namísto globálních proměnných použijeme dvojici proměnných lokálních (přesněji řečeno lokálních v rámci jednoho modulu). První proměnná bude obsahovat pole jmen všech slajdů, druhá pak číslo aktuálního slajdu.
  2. Položky v poli se číslují od jedničky!
  3. Délka pole se zjistí jednoduše pomocí operátoru #.
  4. Funkce mohou začínat v Lue malými písmeny.
  5. Pro načtení souboru se seznamem slajdů použijeme vlastní funkci nazvanouloadSlideList, která využije možnosti standardního modulu io.
  6. Pro zobrazení slajdu (načtení do aktuálního okna) se použije příkazvim.command(„edit jméno_slajdu“).
  7. Mapování funkcí na klávesy se provede pomocí příkazu:vim.command(„map klávesa :lua funkce()<cr>“) – to znamená, že i Lua funkce jsou z tohoto hlediska prakticky plnohodnotnými funkcemi!
  8. Nejsložitější bude registrace funkce volané pro aktualizaci obsahu stavové řádky. Zde si budeme muset pomoci krátkou funkcí naprogramovanou ve Vim Scriptu, která obsahuje volání luaeval. Není to sice příliš elegantní řešení, ale v IT existují mnohem mnohem komplikovanější „mosty“ mezi dvěma programovacími jazyky.

Výsledný skript bude vypadat následovně (podle mého názoru je mnohem čitelnější, než jeho původní varianta):

-- Slideshow tool v1.1
-- Pavel Tisnovsky 2016
 
 
 
-- Pole s nazvy slajdu
local slides = nil
 
-- Prvky v poli se cisluji od jednicky!
local index = 1
 
function loadSlideList(filename)
    local slides = {}
    for line in io.lines(filename) do
        table.insert(slides, line)
    end
    return slides
end
 
function gotoFirstSlide()
    index = 1
end
 
function gotoLastSlide()
    index = #slides
end
 
function beforeFirstSlide()
    return index < 1
end
 
function afterLastSlide()
    return index > #slides
end
 
function showNextSlide()
    index = index + 1
    if afterLastSlide() then
        gotoFirstSlide()
    end
    showActualSlide()
end
 
function showPrevSlide()
    index = index - 1
    if beforeFirstSlide() then
        gotoLastSlide()
    end
    showActualSlide()
end
 
function showFirstSlide()
    gotoFirstSlide()
    showActualSlide()
end
 
function showLastSlide()
    gotoLastSlide()
    showActualSlide()
end
 
function showActualSlide()
    vim.command("edit " .. slides[index])
end
 
function statusLine()
    return "Slide " .. index .. "/" .. #slides .. " : " .. slides[index]
end
 
slides = loadSlideList("list.txt")
 
-- Hot keys
vim.command("map <PageUp>   :lua showPrevSlide()<cr>")
vim.command("map <PageDown> :lua showNextSlide()<cr>")
vim.command("map <Home>     :lua showFirstSlide()<cr>")
vim.command("map <End>      :lua showLastSlide()<cr>")
 
-- Setup
vim.command([[
function! StatusLine()
    return luaeval('statusLine()')
endfunction]])
vim.command("set statusline=%!StatusLine()")
 
-- Potrebujeme zobrazit stavovy radek i ve chvili,
-- kdy je zobrazeno pouze jedno okno
vim.command("set laststatus=2")
 
-- Spustit prezentaci
showFirstSlide()

Obrázek 8: Promítání slajdů v praxi.

Obrázek 9: Promítání slajdů v praxi.

9. Repositář s demonstračními příklady

Všechny demonstrační příklady, s nimiž jsme se v dnešním článku seznámili, byly, podobně jako v předchozích částech tohoto seriálu, uloženy do Git repositáře umístěného na GitHubu (https://github.com/tisnik/pre­sentations):

10. Odkazy na Internetu

  1. Seriál o programovacím jazyku Lua
    http://www.root.cz/serialy/pro­gramovaci-jazyk-lua/
  2. Lua (programming language)
    http://en.wikipedia.org/wi­ki/Lua_(programming_langu­age)
  3. Lua 5.2 sources
    http://www.lua.org/source/5.2/
  4. Pyclewn installation notes
    http://pyclewn.sourceforge­.net/install.html
  5. pip Installation
    https://pip.pypa.io/en/la­test/installing.html
  6. Clewn
    http://clewn.sourceforge.net/
  7. Clewn installation
    http://clewn.sourceforge.net/in­stall.html
  8. Clewn – soubory
    http://sourceforge.net/pro­jects/clewn/files/OldFiles/
  9. Writing Vim Plugins
    http://stevelosh.com/blog/2011/09/wri­ting-vim-plugins/
  10. how to understand this vim script?
    http://stackoverflow.com/qu­estions/12625091/how-to-understand-this-vim-script
  11. Novinky ve VIM 7: Skriptovací jazyk
    http://www.root.cz/vim-sedm-druha-cast/
  12. DirDiff.vim : A plugin to diff and merge two directories recursively.
    http://www.vim.org/scripts/scrip­t.php?script_id=102
  13. vim-dirdiff na GitHubu
    https://github.com/will133/vim-dirdiff
  14. fakeclip : pseudo clipboard register for non-GUI version of Vim
    http://www.vim.org/scripts/scrip­t.php?script_id=2098
  15. vim-fakeclip na GitHubu
    https://github.com/kana/vim-fakeclip
  16. vim-fakeclip: Dokumentace
    http://kana.github.io/con­fig/vim/fakeclip.html
  17. Vim Multiple Cursors na GitHubu
    https://github.com/terryma/vim-multiple-cursors
  18. SLIME (Wikipedia)
    http://en.wikipedia.org/wiki/SLIME
  19. vim-slime na GitHubu
    https://github.com/jpalardy/vim-slime
  20. vi Editor Commands
    http://www.cs.rit.edu/~cslab/vi­.html#A1.4
  21. vi Manual
    http://www.cs.fsu.edu/gene­ral/vimanual.html
  22. Mastering the Vi Editor
    http://www.susnet.uk/mastering-the-vi-editor
  23. Using undo branches
    http://vim.wikia.com/wiki/U­sing_undo_branches
  24. Gundo
    http://sjl.bitbucket.org/gundo.vim/
  25. Vim as a Python IDE, or Python IDE as Vim
    http://blog.jetbrains.com/pychar­m/2013/06/vim-as-a-python-ide-or-python-ide-as-vim/
  26. histwin na GitHubu
    https://github.com/chrisbra/his­twin.vim
  27. histwin.vim : Browse the undo tree
    http://www.vim.org/scripts/scrip­t.php?script_id=2932
  28. undotree.vim : Display your undo history in a graph
    http://www.vim.org/scripts/scrip­t.php?script_id=4177
  29. Surround
    http://www.bestofvim.com/plu­gin/surround/
  30. SnipMate
    http://www.bestofvim.com/plu­gin/snipmate/
  31. Getting a Clojure REPL in Vim With VimClojure, Nailgun, and Leiningen
    http://naleid.com/blog/2011/12/19/get­ting-a-clojure-repl-in-vim-with-vimclojure-nailgun-and-leiningen/
  32. The NERD Commenter : A plugin that allows for easy commenting of code for many filetypes.
    http://www.vim.org/scripts/scrip­t.php?script_id=1218
  33. NERD Commenter na GitHubu
    https://github.com/scroolo­ose/nerdcommenter
  34. luarefvim : Lua reference manual
    http://www.vim.org/scripts/scrip­t.php?script_id=1291
  35. lua.vim : Lua file type plug-in for the Vim text editor
    http://www.vim.org/scripts/scrip­t.php?script_id=3625
  36. vim-lua-ftplugin
    https://github.com/xolox/vim-lua-ftplugin
  37. Vi Improved
    https://wiki.python.org/moin/Vim
  38. javacomplete : Omni Completion for JAVA
    http://www.vim.org/scripts/scrip­t.php?script_id=1785
  39. SearchComplete
    http://www.vim.org/scripts/scrip­t.php?script_id=474
  40. ShowMarks
    http://www.vim.org/scripts/scrip­t.php?script_id=152
  41. ctrlp.vim
    https://github.com/kien/ctrlp.vim
  42. ctrlp.vim
    http://kien.github.io/ctrlp.vim/
  43. vim-signature
    https://github.com/kshenoy/vim-signature
  44. Supertab
    http://www.vim.org/scripts/scrip­t.php?script_id=1643
  45. Supertab (GitHub)
    https://github.com/ervandew/supertab
  46. Vim Essential Plugin: NERD Tree
    http://code.tutsplus.com/tutorials/vim-essential-plugin-nerdtree–net-19692
  47. The NERD tree: A tree explorer plugin for navigating the filesystem
    http://vim.sourceforge.net/scrip­ts/script.php?script_id=1658
  48. NERD Tree Guide
    http://usevim.com/2012/07/18/ner­dtree/
  49. vcscommand.vim : CVS/SVN/SVK/git/hg/bzr integration plugin
    http://www.vim.org/scripts/scrip­t.php?script_id=90
  50. vcscommand na GitHubu
    https://github.com/vim-scripts/vcscommand.vim
  51. Popis skriptu Vim Pathogen
    http://www.vim.org/scripts/scrip­t.php?script_id=2332
  52. Posledníverze skriptu Vim Pathogen
    https://tpo.pe/pathogen.vim
  53. Nejlepší pluginy pro Vim
    http://vimawesome.com/
  54. Nejlepší pluginy pro Vim
    http://www.vim.org/scripts/scrip­t_search_results.php?order_by=ra­ting
  55. Vim-airline na GitHubu
    https://github.com/bling/vim-airline
  56. Vim-airline na www.vim.org
    http://www.vim.org/scripts/dow­nload_script.php?src_id=22726
  57. Vim-fugitive na GitHubu
    https://github.com/tpope/vim-fugitive
  58. Vim-fugitive na www.vim.org
    http://www.vim.org/scripts/scrip­t.php?script_id=2975
  59. Textový editor Vim jako IDE (seriál)
    http://www.root.cz/clanky/textovy-editor-vim-jako-ide/
  60. Building Vim
    http://vim.wikia.com/wiki/Bu­ilding_Vim
  61. Getting the Vim source with Mercurial
    http://vim.wikia.com/wiki/Get­ting_the_Vim_source_with_Mer­curial
  62. Vim Perl Interface
    http://vim.dindinx.net/vim7/html/if_per­l.txt.php
  63. Vim Perl Support
    http://www.softpanorama.or­g/Editors/Vimorama/vim_per­l_support.shtml
  64. VIM as Python IDE
    http://blog.dispatched.ch/2009/05/24/vim-as-python-ide/
  65. Stack Overflow: VIM: Perl interface: passing a variable to Perl and reading a vim variable from Perl
    http://stackoverflow.com/qu­estions/4999902/vim-perl-interface-passing-a-variable-to-perl-and-reading-a-vim-variable-from
  66. Stack Overflow: Getting started with vim scripting with Perl
    http://stackoverflow.com/qu­estions/2208618/getting-started-with-vim-scripting-with-perl
  67. Python with a modular IDE (Vim)
    http://www.sontek.net/python-with-a-modular-ide-vim
  68. Getting to VIM's Python interface
    http://zerokspot.com/weblog/2009/02/21/get­ting-to-know-vims-python-interface/
  69. Pretty-formatting XML
    http://vim.wikia.com/wiki/Pretty-formatting_XML
  70. Delete a pair of XML/HTML tags
    http://vim.wikia.com/wiki/De­lete_a_pair_of_XML/HTML_tags
  71. Vim as XML Editor
    http://www.pinkjuice.com/how­to/vimxml/
  72. xmledit: A filetype plugin to help edit XML, HTML, and SGML documents
    http://www.vim.org/scripts/scrip­t.php?script_id=301
  73. Poslední vývojová verze makra xmledit
    http://github.com/sukima/xmledit/
  74. vim.wikia: Display date-and-time on status line
    http://vim.wikia.com/wiki/Display_date-and-time_on_status_line
  75. vim.wikia: Writing a valid statusline
    http://vim.wikia.com/wiki/Wri­ting_a_valid_statusline
  76. vim.wikia: Statusline tab level ruler
    http://vim.wikia.com/wiki/Sta­tusline_tab_level_ruler
  77. vim.wikia: Switching between different statuslines
    http://vim.wikia.com/wiki/Swit­ching_between_different_sta­tuslines
  78. X Selections, Cut Buffers, and Kill Rings
    http://www.jwz.org/doc/x-cut-and-paste.html
  79. Accessing the system clipboard
    http://vim.wikia.com/wiki/Ac­cessing_the_system_clipbo­ard
  80. xcutsel(1) – Linux man page
    http://linux.die.net/man/1/xcutsel
  81. snipMate : TextMate-style snippets for Vim
    http://www.vim.org/scripts/scrip­t.php?script_id=2540
  82. msanders / snipmate.vim
    https://github.com/msander­s/snipmate.vim
  83. snipMate.vim Introductory Screencast
    http://vimeo.com/3535418
  84. Clewn home page
    http://clewn.sourceforge.net/
  85. How to connect vim with gdb – using clewn
    http://chunhao.net/blog/how-to-connect-vim-with-gdb-using-clewn
  86. yavdb : Yet Another (Generic) Vim Debugger Integration
    http://www.vim.org/scripts/scrip­t.php?script_id=1954
  87. Vim home page
    http://www.vim.org/
  88. vim (man page)
    http://www.linux-tutorial.info/modules.php?na­me=ManPage&sec=1&manpage=vim
  89. Tutorial: Make Vim as Your C/C++ IDE Using c.vim Plugin
    http://www.thegeekstuff.com/2009/01/tu­torial-make-vim-as-your-cc-ide-using-cvim-plugin/
  90. c.vim : C/C++ IDE
    http://vim.sourceforge.net/scrip­ts/script.php?script_id=213
  91. c.vim : C/C++ IDE key mappings
    http://lug.fh-swf.de/vim/vim-c/c-hotkeys.pdf
  92. Základní základy editoru Vim
    http://www.root.cz/clanky/zakladni-zaklady-editoru-vim/
  93. Jak si přizpůsobit Vim
    http://www.root.cz/serialy/jak-si-prizpusobit-vim/
  94. Taglist (plugin)
    http://www.vim.org/scripts/scrip­t.php?script_id=273
  95. The NERD tree: A tree explorer plugin for navigating the filesystem
    http://www.vim.org/scripts/scrip­t.php?script_id=1658
  96. JavaBrowser : Shows java file class, package in a tree as in IDEs. Java source browser.
    http://www.vim.org/scripts/scrip­t.php?script_id=588
  97. snippetsEmu : An attempt to emulate TextMate's snippet expansion
    http://www.vim.org/scripts/scrip­t.php?script_id=1318
  98. Vim plugins for developers
    http://www.linuxtoday.com/upload/vim-plugins-for-developers-140619094010.html
Lupa.cz: Jak EET vidí ajťák aneb Drahá vražda UX

Jak EET vidí ajťák aneb Drahá vražda UX

120na80.cz: Jak si udržet zdravou vaginu

Jak si udržet zdravou vaginu

120na80.cz: Vyzrajte na návaly a pocení v přechodu

Vyzrajte na návaly a pocení v přechodu

120na80.cz: 5 triků, jak zastavit krvácení po holení

5 triků, jak zastavit krvácení po holení

Podnikatel.cz: Eshopy s dopravou zdarma. Zválcují ostatní?

Eshopy s dopravou zdarma. Zválcují ostatní?

Vitalia.cz: Mražené ryby z Makra byly falšované

Mražené ryby z Makra byly falšované

Vitalia.cz: Syndrom PC vidění: stačí dvě hodiny denně

Syndrom PC vidění: stačí dvě hodiny denně

DigiZone.cz: Šlágr TV: pokuta 100 tisíc za on-line

Šlágr TV: pokuta 100 tisíc za on-line

Vitalia.cz: Proč v Penamu nesypou koblihu moučkovým cukrem

Proč v Penamu nesypou koblihu moučkovým cukrem

Vitalia.cz: Martin Kasa o byznysu s léky

Martin Kasa o byznysu s léky

Lupa.cz: Zaplatíme ti, když ti seženeme práci

Zaplatíme ti, když ti seženeme práci

Vitalia.cz: Děti jsou sportem opotřebované

Děti jsou sportem opotřebované

DigiZone.cz: Konec geoblokace? Ani náhodou…

Konec geoblokace? Ani náhodou…

Vitalia.cz: 7 nemocí očí, které musíte léčit včas

7 nemocí očí, které musíte léčit včas

Vitalia.cz: Tetanus v USA – i po odřeninách

Tetanus v USA – i po odřeninách

Vitalia.cz: Ministerstvo: tyto příbory jsou nebezpečné

Ministerstvo: tyto příbory jsou nebezpečné

Lupa.cz: Nová podoba Instagramu? Katastrofa

Nová podoba Instagramu? Katastrofa

Podnikatel.cz: Šizený guláš na pultě. Jako Lidl to nedělejte

Šizený guláš na pultě. Jako Lidl to nedělejte

DigiZone.cz: DAB+ versus FM, ČRo a ČRa proti APSV

DAB+ versus FM, ČRo a ČRa proti APSV

Podnikatel.cz: Když už je sexy, tak ať taky funguje

Když už je sexy, tak ať taky funguje