Hlavní navigace

Tvorba TUI s knihovnou prompt_toolkit: aplikace s celoobrazovkovým rozhraním

Pavel Tišnovský

Čtvrtý článek o knihovně prompt_toolkit je věnován popisu způsobu deklarace textového uživatelského rozhraní (TUI) se základními ovládacími prvky rozmístěnými na ploše terminálu s využitím takzvaných správců rozložení.

Doba čtení: 32 minut

Obsah

1. Tvorba textového uživatelského rozhraní s knihovnou prompt_toolkit: aplikace s celoobrazovkovým rozhraním

2. Vytvoření kostry aplikace s TUI postavené nad knihovnou prompt_toolkit

3. Přepnutí do režimu zobrazení využívajícího celou plochu terminálu

4. Základní prvky TUI: kontejnery a prvky pro vstup/výstup textových údajů

5. Naprogramované reakce na klávesové zkratky

6. Vertikální rozmístění prvků TUI v ploše terminálu

7. Použití prvku typu Window ve funkci oddělovače

8. Horizontální rozmístění prvků TUI v ploše terminálu

9. Současné použití správců rozložení s vertikálním i horizontálním rozmístěním prvků TUI

10. Další ovládací prvky, z nichž se skládají aplikace s textovým uživatelským rozhraním

11. Prvky Frame a Box

12. Nastavení stylu zobrazení prvku typu FrameBox

13. Použití prvku typu Label

14. Prvek typu TextArea aneb textový editor snadno a rychle

15. Ovládací prvek typu Button

16. Přepínání fokusu (zaměření, výběru) mezi jednotlivými tlačítky

17. Zákaz přenosu fokusu na zvolený ovládací prvek; přepínání pomocí kláves Tab a Shift+Tab

18. Nastavení stylu zobrazení ovládacích prvků TUI

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

20. Odkazy na Internetu

1. Tvorba textového uživatelského rozhraní s knihovnou prompt_toolkit: aplikace s celoobrazovkovým rozhraním

Na předchozí trojici článků [1] [2] [3] dnes navážeme, protože si řekneme, jaké základní ovládací prvky (widgety) je možné využít při tvorbě textového uživatelského rozhraní založeného na knihovně prompt_toolkit. Taktéž se seznámíme s takzvanými správci rozvržení (layout managers), které ovládací prvky vhodným způsobem uspořádají na plochu terminálu.

Obrázek 1: Dialog pro výběr odpovědi typu Ano/Ne, který je představován funkcí yes_no_dialog, tentokrát plně počeštěný díky podpoře Unicode.

Poznámka: podobně, jako tomu bylo ve všech třech předchozích článcích, budou i dnes všechny screenshoty pořízeny na terminálu XTerm s nastavenými 25 textovými řádky a 80 znaky na řádek. Sami si však můžete vyzkoušet, že aplikace budou automaticky reagovat na změnu velikosti terminálu (samozřejmě v rozumných mezích, problém nastane při zmenšení terminálu pod přibližně 30×10 znaků, kdy se vypíše chybové hlášení „Window too small“). Velikost terminálu lze změnit i v během činnosti aplikací.

Obrázek 2: Dialog typu button_dialog se třemi specifikovanými tlačítky.

2. Vytvoření kostry aplikace s TUI postavené nad knihovnou prompt_toolkit

Aplikace s plnohodnotným TUI jsou při použití knihovny prompt_toolkit představovány instancí třídy prompt_toolkit.application­.Application. Typicky se konstruktoru této třídy předává takzvaný layout s prvky TUI, nastavené klávesové zkratky atd. Po zavolání metody run() se spustí smyčka událostí (event loop), která se bude mj. starat o reakce ovládacích prvků na akce prováděné uživatelem. V prvním demonstračním příkladu, který si dnes ukážeme, se pouze vytvoří objekt typu Application představující ústřední část aplikace s textovým uživatelským rozhraním. Následně je zavolána metoda run(), která aplikaci spustí. Ovšem vzhledem k tomu, že v aplikaci nejsou definovány žádné prvky textového uživatelského rozhraní, pouze se vypíše zpráva „No layout specified. Press ENTER to quit.“ a aplikace bude čekat na své ukončení stiskem klávesy Enter:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application
 
 
# vytvoření aplikace s textovým uživatelským rozhraním
application = Application()
 
# spuštění aplikace
application.run()

Obrázek 3: Vzhledem k tomu, že v aplikaci nejsou specifikovány žádné prvky textového uživatelského rozhraní, vypíše se po jejím spuštění pouze tato zpráva a aplikace bude po stisku klávesy Enter ukončena.

Ve skutečnosti budou všechny následující demonstrační příklady postaveny na poněkud odlišném skriptu, který se od prvního demonstračního příkladu odlišuje pouze tím, že se v něm explicitně používá funkce main. Úplný zdrojový kód tohoto příkladu vypadá následovně:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
&#k03nbsp;
from prompt_toolkit import Application
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application()
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

Obrázek 4: I po spuštění tohoto skriptu se vypíše stejná zpráva, jako ve skriptu prvním.

Jen pro zajímavost si připomeňme, jak vypadá kostra aplikace při použití knihovny appJar, s níž jsme se již na stránkách Roota seznámili:

#!/usr/bin/env python
 
from appJar import gui
 
app = gui()
 
app.go()

3. Přepnutí do režimu zobrazení využívajícího celou plochu terminálu

Konstruktoru třídy Application je možné předat několik nepovinných (pojmenovaných) parametrů, především pak:

Parametr Význam
layout objekt nesoucí informace o všech ovládacích prvcích
key_bindings nastavené klávesové zkratky
clipboard objekt představující textovou schránku
full_screen režim vyplnění celé plochy terminálu
erase_when_done povolení vymazání obrazovky před ukončením aplikace
Poznámka: v dokumentaci jsou sice zmíněny parametry on_abort a on_exit, ovšem ty nejsou podporovány (je zapotřebí opravit dokumentační řetězec konstruktoru).

Mnoho aplikací s textovým uživatelským rozhraním (například Midnight Commander a všechny textové editory) používají pro své zobrazení celou dostupnou plochu terminálu. Toto chování se povolí použitím pojmenovaného parametru full_screen:

application = Application(full_screen=True)

Opět se podívejme na demonstrační příklad (režim plné obrazovky bude použit i ve všech dalších příkladech):

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

Obrázek 5: Výsledek spuštění předchozího skriptu – aplikace je skutečně spuštěna přes celou plochu terminálu.

4. Základní prvky TUI: kontejnery a prvky pro vstup/výstup textových údajů

Mezi základní třídy, z nichž se v knihovně prompt_toolkit skládá textové uživatelské rozhraní, patří především třída nazvaná UIControl a taktéž třída Container. Jedná se o bázové třídy reprezentující libovolný prvek TUI, resp. zajišťující zabalení a umístění tohoto prvku na ploše terminálu. Od třídy Container jsou odvozeny další třídy, především pak následující čtveřice:

Třída Stručný popis
HSplit zajišťuje horizontální rozložení prvků na ploše
VSplit zajišťuje vertikální rozložení prvků na ploše
FloatContainer používá se například pro menu a další „plovoucí“ prvky
Window kontejner, který obaluje jeden konkrétní ovládací prvek

Od třídy UIControl jsou odvozeny především třídy:

Třída Stručný popis
FormattedTextControl zajišťuje vykreslení naformátovaného textu
BufferControl zobrazí vstupní buffer
Poznámka: instanci BufferControl využívá i metoda prompt(), s níž jsme se seznámili v úvodní části tohoto miniseriálu.

Prozatím si v demonstračních příkladech vystačíme s prvkem FormattedTextControl. Postup při jeho zobrazení na ploše terminálu je následující:

Nejprve vytvoříme naformátovanou zprávu (viz předchozí článek) a následně tuto zprávu předáme konstruktoru třídy FormattedTextControl:

# naformátovaná zpráva
message = HTML("<ansired>Hello</ansired> <ansiblue>world!</ansiblue>")
 
# ovládací prvek s naformátovaným textem
text = FormattedTextControl(text=message)

Dále je nutné vytvořený ovládací prvek vložit do vhodného kontejneru. Nejjednodušší bude, alespoň prozatím, použití kontejneru Window:

# okno obsahující jediný ovládací prvek
window = Window(content=text)

Následně vytvoříme správce rozvržení a (opět v konstruktoru) specifikujeme, který kontejner se má zobrazit:

# správce rozvržení
layout = Layout(window)

5. Naprogramované reakce na klávesové zkratky

Předchozí řádky vlastně popisovaly pouze vzhled aplikace; zbývá doplnit informace o jejím chování. Prozatím se spokojíme s tím, že aplikaci bude možné ukončit klávesou Escape. Vzhledem k tomu, že smyčka událostí je řízena přímo instancí třídy Application, musíme tomuto objektu nějakým způsobem předat informaci o tom, jak má na klávesu Escape reagovat. To zajišťuje další část kódu, v níž vytvoříme instanci třídy KeyBindings, pomocnou callback funkci on_escape_press, která aplikaci ukončí a s využitím anotace navážeme tuto callback funkci právě na stisk klávesy Escape:

# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()

Instanci třídy KeyBindings pak předáme konstruktoru Application:

# vytvoření aplikace s textovým uživatelským rozhraním
application = Application(layout=layout,
                          key_bindings=key_bindings,
                          full_screen=True)

Obrázek 6: Takto vypadá první aplikace se skutečným textovým uživatelským rozhraním po svém spuštění.

Úplný zdrojový kód tohoto příkladu je již poměrně komplikovaný, ovšem vytvořili jsme v něm užitečný základ TUI (což bude patrné z příkladů dalších):

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout.layout import Layout
from prompt_toolkit.key_binding import KeyBindings
 
 
# naformátovaná zpráva
message = HTML("<ansired>Hello</ansired> <ansiblue>world!</ansiblue>")
 
# ovládací prvek s naformátovaným textem
text = FormattedTextControl(text=message)
 
# okno obsahující jediný ovládací prvek
window = Window(content=text)
 
# správce rozvržení
layout = Layout(window)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

6. Vertikální rozmístění prvků TUI v ploše terminálu

Jednotlivé prvky textového uživatelského rozhraní je možné na ploše terminálu rozmístit různými způsoby s využitím takzvaných správců rozvržení (layout managers), které se ovšem v knihovně prompt_toolkit nazývají kontejnery. Mezi kontejnery patří především tyto tři třídy:

  1. HSplit
  2. VSplit
  3. FlowContainer
  4. Window
  5. ConditionalContainer

Nejprve si ukažme příklad použití kontejneru VSplit. Ten slouží pro rozmístění prvků vertikálně – všechny prvky, které do tohoto kontejneru vložíme, budou umístěny vedle sebe v pořadí zleva doprava:

+-----------+------------+------------+------------+
|           |            |            |            |
|  prvek #1 |  prvek #2  |  prvek #3  |  prvek #4  |
|           |            |            |            |
+-----------+------------+------------+------------+

Prvky se do kontejneru předávají již při jeho konstrukci, a to konkrétně v seznamu (povšimněte si hranatých závorek). Počet takto vložených prvků TUI není teoreticky nijak omezen; prakticky jsme samozřejmě omezeni šířkou terminálu, tj. počtem znaků na řádku. Pokud se prvky na šířku terminálu nevejdou, vypíše se zpráva „Window too small“:

# správce rozvržení
vsplit = VSplit([
    window1,
    window2,
    window3])

Jakmile máme objekt typu VSplit vytvořen, můžeme ho předat konstruktoru třídy Layout. Tento objekt si mj. pamatuje i prvek, který má nastaven fokus:

layout = Layout(vsplit)

Následně se layout předá do konstruktoru třídy Application:

application = Application(layout=layout, full_screen=True)
Poznámka: do kontejnerů je možné vložit jak přímo jednotlivé prvky TUI, tak i další kontejnery a vytvořit tak i poměrně složitě strukturované uživatelské rozhraní.

Obrázek 7: Tři prvky textového uživatelského rozhraní rozmístěné vertikálně (vedle sebe).

Úplný zdrojový kód příkladu využívajícího vertikální rozmístění prvků TUI vypadá takto:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, VSplit
from prompt_toolkit.key_binding import KeyBindings
 
 
# naformátované zprávy
message1 = HTML("<ansired>Hello</ansired>")
message2 = HTML("<ansiblue>world!</ansiblue>")
message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>")
 
# ovládací prvky s naformátovaným textem
text1 = FormattedTextControl(text=message1)
text2 = FormattedTextControl(text=message2)
text3 = FormattedTextControl(text=message3)
 
# okna obsahující jediný ovládací prvek
window1 = Window(content=text1)
window2 = Window(content=text2)
window3 = Window(content=text3)
 
# správce rozvržení
vsplit = VSplit([
    window1,
    window2,
    window3])
 
layout = Layout(vsplit)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

7. Použití prvku typu Window ve funkci oddělovače

Kontejneru Window je možné v jeho konstruktoru předat poměrně velké množství volitelných parametrů ovlivňujících jeho chování. Lze například nastavit rozměry okna s využitím parametrů width a height, povolit scrollovací lišty, nastavit styl zobrazení nebo zvolit, jakým znakem má být vyplněna plocha okna. A právě vhodnou kombinací parametrů width a char můžeme dosáhnout toho, že se okno bude chovat jako (viditelný) vertikální oddělovač dalších prvků TUI (samozřejmě lze nastavit i styl atd., to si ukážeme dále):

# správce rozvržení
vsplit = VSplit([
    window1,
    Window(width=1, char='|'),
    window2,
    Window(width=1, char='|'),
    window3])
 
layout = Layout(vsplit)
Poznámka: pokud použijete terminál se skutečně velkou plochou, může se stát, že se i při zadání width=1 okno rozšíří. Pro jistotu je možné navíc specifikovat i parametr dont_extend_width=True, který toto rozšíření za všech podmínek zakáže.

Obrázek 8: Tři prvky textového uživatelského rozhraní, mezi nimiž jsou použita úzká okna plnící úlohu vizuálního oddělovače.

Úplný demonstrační příklad, v němž se používají dvě úzká okna ve funkci oddělovače, vypadá následovně:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, VSplit
from prompt_toolkit.key_binding import KeyBindings
 
 
# naformátované zprávy
message1 = HTML("<ansired>Hello</ansired>")
message2 = HTML("<ansiblue>world!</ansiblue>")
message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>")
 
# ovládací prvky s naformátovaným textem
text1 = FormattedTextControl(text=message1)
text2 = FormattedTextControl(text=message2)
text3 = FormattedTextControl(text=message3)
 
# okna obsahující jediný ovládací prvek
window1 = Window(content=text1)
window2 = Window(content=text2)
window3 = Window(content=text3)
 
# správce rozvržení
vsplit = VSplit([
    window1,
    Window(width=1, char='|'),
    window2,
    Window(width=1, char='|'),
    window3])
layout = Layout(vsplit)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

8. Horizontální rozmístění prvků TUI v ploše terminálu

Podobně jako jsme si v předchozích dvou kapitolách ukázali vertikální rozmístění prvků textového uživatelského rozhraní s využitím správce rozmístění pojmenovaného VSplit, je samozřejmě možné prvky rozmístit i horizontálně, a to pomocí správce nazvaného příhodně HSplit. Jeho základní použití je prakticky totožné – konstruktoru se předá seznam prvků TUI, které mají být zobrazeny v horizontálních pruzích:

# správce rozvržení
hsplit = HSplit([
    window1,
    window2,
    window3])
 
layout = Layout(hsplit)

Obrázek 9: Aplikace, v níž jsou tři prvky TUI rozmístěny horizontálně (bez oddělovače).

Následuje úplný zdrojový kód tohoto příkladu:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit
from prompt_toolkit.key_binding import KeyBindings
 
 
# naformátované zprávy
message1 = HTML("<ansired>Hello</ansired>")
message2 = HTML("<ansiblue>world!</ansiblue>")
message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>")
 
# ovládací prvky s naformátovaným textem
text1 = FormattedTextControl(text=message1)
text2 = FormattedTextControl(text=message2)
text3 = FormattedTextControl(text=message3)
 
# okna obsahující jediný ovládací prvek
window1 = Window(content=text1)
window2 = Window(content=text2)
window3 = Window(content=text3)
 
# správce rozvržení
hsplit = HSplit([
    window1,
    window2,
    window3])
 
layout = Layout(hsplit)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

Okna o výšce jeden znak (resp. přesněji řečeno jeden textový řádek) mohou sloužit jako vizuální oddělovače mezi prvky textového uživatelského rozhraní. Celý systém, zde konkrétně se třemi oddělenými prvky, může vypadat následovně:

# správce rozvržení
hsplit = HSplit([
    window1,
    Window(height=1, char='-'),
    window2,
    Window(height=1, char='-'),
    window3])
 
layout = Layout(hsplit)

Obrázek 10: Aplikace, v níž jsou tři prvky TUI rozmístěny horizontálně a navíc jsou mezi tyto prvky vložena okna o výšce jeden znak, které plní funkci oddělovače.

Opět si ukažme úplný zdrojový kód tohoto příkladu:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit
from prompt_toolkit.key_binding import KeyBindings
 
 
# naformátované zprávy
message1 = HTML("<ansired>Hello</ansired>")
message2 = HTML("<ansiblue>world!</ansiblue>")
message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>")
 
# ovládací prvky s naformátovaným textem
text1 = FormattedTextControl(text=message1)
text2 = FormattedTextControl(text=message2)
text3 = FormattedTextControl(text=message3)
 
# okna obsahující jediný ovládací prvek
window1 = Window(content=text1)
window2 = Window(content=text2)
window3 = Window(content=text3)
 
# správce rozvržení
hsplit = HSplit([
    window1,
    Window(height=1, char='-'),
    window2,
    Window(height=1, char='-'),
    window3])
 
layout = Layout(hsplit)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

9. Současné použití správců rozložení s vertikálním i horizontálním rozmístěním prvků TUI

Vzhledem k tomu, že do jednoho kontejneru můžeme vložit jak přímo jednotlivé prvky TUI, tak i další kontejnery, je možné libovolným způsobem kombinovat správce pro horizontální a vertikální rozložení. To je ukázáno v dalším úryvku kódu, v němž je plocha terminálu rozdělena horizontálně na tři pruhy (horní plocha, jednořádkové okno – oddělovač, dolní plocha), přičemž horní plocha je dále rozdělena na tři podplochy (ovládací prvek, jednosloupcové okno – oddělovač, druhý ovládací prvek):

# správce rozvržení
vsplit = HSplit([
    VSplit([
        window1,
        Window(width=1, char='|'),
        window2]),
    Window(height=1, char='-'),
    window3])
 
layout = Layout(vsplit)

Obrázek 11: Aplikace používající kombinaci horizontální a vertikálního rozložení prvků TUI.

Opět si ukažme úplný zdrojový kód tohoto příkladu:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
 
 
# naformátované zprávy
message1 = HTML("<ansired>Hello</ansired>")
message2 = HTML("<ansiblue>world!</ansiblue>")
message3 = HTML("<ansiyellow>(Esc to quit)</ansiyellow>")
 
# ovládací prvky s naformátovaným textem
text1 = FormattedTextControl(text=message1)
text2 = FormattedTextControl(text=message2)
text3 = FormattedTextControl(text=message3)
 
# okna obsahující jediný ovládací prvek
window1 = Window(content=text1)
window2 = Window(content=text2)
window3 = Window(content=text3)
 
# správce rozvržení
vsplit = HSplit([
    VSplit([
        window1,
        Window(width=1, char='|'),
        window2]),
    Window(height=1, char='-'),
    window3])
 
layout = Layout(vsplit)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

10. Další ovládací prvky, z nichž se skládají aplikace s textovým uživatelským rozhraním

Kromě základních ovládacích prvků FormattedTextControl a BufferControl, které jsou odvozeny přímo od bázové třídy UIControl, je možné použít i plnohodnotné widgety: tlačítka, textová návěští, menu atd. Tyto widgety většinou interně používají kombinaci tříd Window a FormattedTextControl, popř. Window a BufferControl, což vlastně jen dokazuje, že tvorba TUI je v mnoha ohledech jednodušší, než tomu je u plnohodnotného GUI:

Ovládací prvek Stručný popis
Label textové návěští
Button tlačítko (může získat fokus a reagovat na stlačení)
Checkbox zaškrtávací tlačítko
RadioList skupina přepínacích tlačítek
TextArea vstupní textové pole (textový editor)
Frame rámeček okolo libovolného prvku nebo skupiny prvků
Shadow stín pod libovolným prvkem nebo skupinou prvků
Box okraj okolo libovolného prvku nebo skupiny prvků
HorizontalLine oddělovací čára
VerticalLine oddělovací čára
ProgressBar zobrazení probíhající činnosti

11. Prvky Frame a Box

První prvky z předchozího seznamu, s nimiž se seznámíme, jsou pasivní, tj. nereagují na žádné akce prováděné uživatelem a slouží pouze pro lepší pozicování prvků aktivních. Jedná se o prvky Frame a Box. Jedním z důvodů, proč si tyto prvky popisujeme ve stejné kapitole je fakt, že se skutečně používají společně, protože Frame slouží k vytvoření viditelného rámečku okolo jiného prvku/kontejneru, zatímco Box k vytvoření neviditelného okraje. Základní použití je následující:

# struktura obrazovky
root = Box(Frame(widget))

Obrázek 12: Použití prvků Box a Frame okolo zprávy zobrazené prvkem Label (návěští).

Podívejme se na způsob vložení návěští do prvků Frame a Box. Jak je patrné, mohou oba tyto prvky sloužit jako kontejnery:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.widgets import *
 
 
# naformátovaná zpráva
message = HTML("<ansired>Hello</ansired> <ansiblue>world!</ansiblue>")
 
# widget
widget = Label(message)
 
# struktura obrazovky
root = Box(Frame(widget))
 
# správce rozvržení
layout = Layout(container=root)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

12. Nastavení stylu zobrazení prvku typu FrameBox

U prvků typu Box a Frame je možné měnit styl zobrazení. Okraj lze nastavit na libovolnou hodnotu počítanou ve znacích, popř. textových řádcích, styl rámečku je ovlivněn parametrem style, což je ostatně stejné i pro všechny další prvky TUI:

# struktura obrazovky
root = Box(Frame(widget, title="About:", style="bg:#ansiblue #ansiwhite"),
           padding=2)

Výsledek můžeme vidět na dalším screenshotu:

Obrázek 13: Nastavení stylu zobrazení prvků typu Frame a Box.

Opět si ukažme příklad, v němž se styl rámečku nastavuje:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.widgets import *
 
 
# naformátovaná zpráva
message = HTML("<ansibrightred>Hello</ansibrightred> " +
               "<ansibrightyellow>world!</ansibrightyellow>")
 
# widget
widget = Label(message)
 
# struktura obrazovky
root = Box(Frame(widget, title="About:", style="bg:#ansiblue #ansiwhite"),
           padding=2)
 
# správce rozvržení
layout = Layout(container=root)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

13. Použití prvku typu Label

Textové návěští, jehož obsah se samozřejmě dá programově modifikovat, je reprezentováno třídou Label. Podobně jako v prakticky všech dalších widgetech je možné i zde při specifikaci zobrazené zprávy použít formátování s využitím minule popsaných tříd ANSI či HTML:

message1 = HTML("<ansibrightred>Hello</ansibrightred>")
widget1 = Label(message1)
...
...
...

Obrázek 14: Tři prvky typu Label na ploše aplikace, každý zobrazený v ostylovaném rámečku.

Celý zdrojový kód příkladu, v němž jsou použita tři návěští, vypadá následovně:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.widgets import *
 
 
# naformátované zprávy
message1 = HTML("<ansibrightred>Hello</ansibrightred>")
message2 = HTML("<ansibrightyellow>world!</ansibrightyellow>")
message3 = HTML("<ansibrightyellow>(Esc to quit)</ansibrightyellow>")
 
# widgety
widget1 = Label(message1)
widget2 = Label(message2)
widget3 = Label(message3)
 
# styl rámce
style = "bg:#ansiblue #ansiwhite"
 
# správce rozvržení
vsplit = HSplit([
    VSplit([
        Frame(widget1, style=style),
        Frame(widget2, style=style)]),
    Frame(widget3, style=style)])
layout = Layout(vsplit)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

14. Prvek typu TextArea aneb textový editor snadno a rychle

Zatímco byly výše popsané prvky Box, Frame a Label zcela pasivní, je tomu v případě prvku TextArea úplně jinak, protože tato část textového uživatelského rozhraní ve skutečnosti představuje implementaci relativně dobrého textového editoru, v němž je možné využít základní klávesové zkratky, s nimiž jsme se již seznámili při popisu funkce prompt. Vložení editoru do TUI je stejně snadné, jako u jakéhokoli jiného prvku:

vsplit = HSplit([
    VSplit([
        Frame(widget1, style=style),
        Frame(widget2, style=style)]),
    Frame(TextArea(), title="Editor"),
    Frame(widget3, style=style)])
 
layout = Layout(vsplit)

Obrázek 15: Ovládací prvek typu TextArea zobrazený společně se třemi návěštími. Všechny prvky jsou umístěny v rámečku.

S tímto prvkem se podrobněji seznámíme příště, takže již jen krátce demonstrační příklad, který ho využívá:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application, HTML
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.widgets import *
 
 
# naformátované zprávy
message1 = HTML("<ansibrightred>Hello</ansibrightred>")
message2 = HTML("<ansibrightyellow>world!</ansibrightyellow>")
message3 = HTML("<ansibrightyellow>(Esc to quit)</ansibrightyellow>")
 
# widgety
widget1 = Label(message1)
widget2 = Label(message2)
widget3 = Label(message3)
 
# styl rámce
style = "bg:#ansiblue #ansiwhite"
 
# správce rozvržení
vsplit = HSplit([
    VSplit([
        Frame(widget1, style=style),
        Frame(widget2, style=style)]),
    Frame(TextArea(), title="Editor"),
    Frame(widget3, style=style)])
 
layout = Layout(vsplit)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

15. Ovládací prvek typu Button

Dalším aktivním ovládacím prvkem je tlačítko představované instancí třídy Button. Tlačítko může reagovat na svůj stisk, který je obsloužen v callback funkci specifikované nepovinným atributem handler:

button1 = Button('Button 1', handler=button1_clicked)

Obrázek 16: Textové uživatelské rozhraní se čtveřicí tlačítek a pasivní textovou plochou.

V následujícím demonstračním příkladu jsou deklarována čtyři tlačítka. Po stisku prvních třech tlačítek se pouze do textového pole vypíše informace o události která nastala. Poslední tlačítko slouží k ukončení aplikace. Prozatím ovšem nebude možné získat fokus těchto tlačítek, takže je aplikaci nutné ukončit „postaru“ klávesou Escape:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.application.current import get_app
from prompt_toolkit.widgets import *
 
 
def button1_clicked():
    text_area.text += 'Button 1 clicked\n'
 
 
def button2_clicked():
    text_area.text += 'Button 2 clicked\n'
 
 
def button3_clicked():
    text_area.text += 'Button 3 clicked\n'
 
 
def exit_clicked():
    get_app().exit()
 
 
button1 = Button('Button 1', handler=button1_clicked)
button2 = Button('Button 2', handler=button2_clicked)
button3 = Button('Button 3', handler=button3_clicked)
button4 = Button('Exit', handler=exit_clicked)
 
buttons = HSplit([button1,
                  button2,
                  button3,
                  button4])
 
text_area = TextArea()
 
# správce rozvržení
root = VSplit([Box(Frame(buttons, style="bg:#ansiblue #ansiwhite"), padding=2),
               Box(Frame(text_area, title="Events"), padding=2)])
 
layout = Layout(root)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

16. Přepínání fokusu (zaměření, výběru) mezi jednotlivými tlačítky

Ve skutečnosti je možné přepínání fokusu (neboli zaměření či výběru) ovládacích prvků naprogramovat velmi snadno, a to následujícím způsobem:

from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
key_bindings.add('up')(focus_previous)
key_bindings.add('down')(focus_next)

Obrázek 17: Přepínání mezi tlačítky.

Předchozí řádky zajistí, že se při stisku šipky nahoru zavolá funkce focus_previous() a při stisku šipky dolů pak funkce focus_next(). Tyto dvě funkce budou postupně přepínat mezi ovládacími prvky, a to v pořadí, v jakém jsou definovány (toto pořadí je však možné změnit). Příklad, v němž je toto chování naprogramováno, vypadá takto:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
from prompt_toolkit.application.current import get_app
from prompt_toolkit.widgets import *
 
 
def button1_clicked():
    text_area.text += 'Button 1 clicked\n'
 
 
def button2_clicked():
    text_area.text += 'Button 2 clicked\n'
 
 
def button3_clicked():
    text_area.text += 'Button 3 clicked\n'
 
 
def exit_clicked():
    get_app().exit()
 
 
button1 = Button('Button 1', handler=button1_clicked)
button2 = Button('Button 2', handler=button2_clicked)
button3 = Button('Button 3', handler=button3_clicked)
button4 = Button('Exit', handler=exit_clicked)
 
buttons = HSplit([button1,
                  button2,
                  button3,
                  button4])
 
text_area = TextArea()
 
# správce rozvržení
root = VSplit([Box(Frame(buttons, style="bg:#ansiblue #ansiwhite"), padding=2),
               Box(Frame(text_area, title="Events"), padding=2)])
 
layout = Layout(root)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
key_bindings.add('up')(focus_previous)
key_bindings.add('down')(focus_next)
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

17. Zákaz přenosu fokusu na zvolený ovládací prvek; přepínání pomocí kláves Tab a Shift+Tab

Pokud nebudeme chtít, aby se fokus přenesl na některý ovládací prvek, je nutné při jeho konstrukci použít nepovinný parametr focusable a předat mu hodnotu False:

text_area = TextArea(focusable=False)

Další úprava aplikace spočívá v tom, že nastavíme přepínání fokusu na klávesové zkratky Tab a Shift+Tab, což je pro mnoho uživatelů známější (i když podle mého názoru mnohem horší) volba, než použití šipky nahoru a dolů:

key_bindings = KeyBindings()
key_bindings.add('s-tab')(focus_previous)
key_bindings.add('tab')(focus_next)

Opět se podívejme na celý zdrojový kód příkladu, který toto nové chování implementuje:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
from prompt_toolkit.application.current import get_app
from prompt_toolkit.widgets import *
 
 
def button1_clicked():
    text_area.text += 'Button 1 clicked\n'
 
 
def button2_clicked():
    text_area.text += 'Button 2 clicked\n'
 
 
def button3_clicked():
    text_area.text += 'Button 3 clicked\n'
 
 
def exit_clicked():
    get_app().exit()
 
 
button1 = Button('Button 1', handler=button1_clicked)
button2 = Button('Button 2', handler=button2_clicked)
button3 = Button('Button 3', handler=button3_clicked)
button4 = Button('Exit', handler=exit_clicked)
 
buttons = HSplit([button1,
                  button2,
                  button3,
                  button4])
 
text_area = TextArea(focusable=False)
 
# správce rozvržení
root = VSplit([Box(Frame(buttons, style="bg:#ansiblue #ansiwhite"), padding=2),
               Box(Frame(text_area, title="Events"), padding=2)])
 
layout = Layout(root)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
key_bindings.add('s-tab')(focus_previous)
key_bindings.add('tab')(focus_next)
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

18. Nastavení stylu zobrazení ovládacích prvků TUI

V závěru dnešního článku si ukážeme způsob změny stylu zobrazení ovládacích prvků textového uživatelského rozhraní. Nejdříve si připomeňme, že každému prvku můžeme přiřadit libovolnou třídu stylu, a to podobně jako v klasickém CCS, ovšem poněkud odlišným zápisem:

# správce rozvržení
root = VSplit([Box(Frame(buttons, style="class:button_panel"),
                   padding=2),
               Box(Frame(text_area, title="Events", style="class:edit_panel"),
                   padding=2)])

Dále již můžeme specifikovat styly zobrazení, tj. především barvu popředí, pozadí i styl fontu (viz předchozí článek):

style = Style([
    ('button_panel', 'bg:#ansiblue #ansiwhite'),
    ('edit_panel',   'bg:#ansigreen #000000'),
    ('button',       '#ansibrightyellow'),
    ('button focused', 'bg:#ff0000'),
    ('text-area focused', 'bg:#ff0000'),
])

Takto vytvořený styl se předá konstruktoru třídy Application:

# vytvoření aplikace s textovým uživatelským rozhraním
application = Application(layout=layout,
                          key_bindings=key_bindings,
                          full_screen=True,
                          style=style)

Obrázek 18: Textové uživatelské rozhraní aplikace s vlastním nastaveným stylem.

Již naposledy si ukážeme výpis zdrojového kódu příkladu, v němž je použit upravený styl:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
from prompt_toolkit import Application
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
from prompt_toolkit.application.current import get_app
from prompt_toolkit.widgets import *
from prompt_toolkit.styles import Style
 
 
def button1_clicked():
    text_area.text += 'Button 1 clicked\n'
 
 
def button2_clicked():
    text_area.text += 'Button 2 clicked\n'
 
 
def button3_clicked():
    text_area.text += 'Button 3 clicked\n'
 
 
def exit_clicked():
    get_app().exit()
 
 
button1 = Button('Button 1', handler=button1_clicked)
button2 = Button('Button 2', handler=button2_clicked)
button3 = Button('Button 3', handler=button3_clicked)
button4 = Button('Exit', handler=exit_clicked)
 
buttons = HSplit([button1,
                  button2,
                  button3,
                  button4])
 
text_area = TextArea(focusable=False)
 
# správce rozvržení
root = VSplit([Box(Frame(buttons, style="class:button_panel"),
                   padding=2),
               Box(Frame(text_area, title="Events", style="class:edit_panel"),
                   padding=2)])
 
layout = Layout(root)
 
# napojení na klávesové zkratky
key_bindings = KeyBindings()
key_bindings.add('up')(focus_previous)
key_bindings.add('down')(focus_next)
 
style = Style([
    ('button_panel', 'bg:#ansiblue #ansiwhite'),
    ('edit_panel',   'bg:#ansigreen #000000'),
    ('button',       '#ansibrightyellow'),
    ('button focused', 'bg:#ff0000'),
    ('text-area focused', 'bg:#ff0000'),
])
 
 
@key_bindings.add('escape')
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()
 
 
def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True,
                              style=style)
 
    # spuštění aplikace
    application.run()
 
 
if __name__ == '__main__':
    main()

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

Všechny dnes popisované demonstrační příklady byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/pre­sentations. Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již poměrně rozsáhlý) repositář:

# Příklad Popis Odkaz
1 tui01_basic_app.py kostra aplikace s TUI https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui01_basic_ap­p.py
2 tui02_basic_app_with_main.py vylepšená kostra aplikace s TUI https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui02_basic_ap­p_with_main.py
3 tui03_full_screen.py přepnutí do režimu celé obrazovky https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui03_full_scre­en.py
4 tui04_simple_app.py použití základních prvků TUI https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui04_simple_ap­p.py
5 tui05_vsplit.py vertikální rozmístění prvků na obrazovce https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui05_vsplit­.py
6 tui06_window_as_separator.py použití prvku Window ve funkci oddělovače https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui06_window_as_se­parator.py
7 tui07_hsplit.py horizontální rozmístění prvků na obrazovce https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui07_hsplit­.py
8 tui08_window_as_separator.py použití prvku Window ve funkci oddělovače https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui08_window_as_se­parator.py
9 tui09_hsplit_vsplit.py kombinace horizontálního a vertikálního rozdělení https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui09_hsplit_vsplit­.py
10 tui10_frame_box.py použití prvků Box a Frame https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui10_frame_box­.py
11 tui11_frame_box_styles.py nastavení stylů prvků Box a Frame https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui11_frame_box_sty­les.py
12 tui12_frame_box_and_layout.py vylepšený layout aplikace https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui12_frame_box_an­d_layout.py
13 tui13_text_area.py textové pole https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui13_text_a­rea.py
14 tui14_buttons.py použití prvků Button https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui14_button­s.py
15 tui15_buttons_focus.py přepínaní mezi tlačítky https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui15_button­s_focus.py
16 tui16_buttons_switch_by_tab.py přepínaní mezi tlačítky https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui16_button­s_switch_by_tab.py
17 tui17_buttons_styles.py nastavení stylu tlačítek https://github.com/tisnik/pre­sentations/blob/master/prom­pt_toolkit/tui/tui17_button­s_styles.py

20. Odkazy na Internetu

  1. UTF-8 encoded sample plain-text file
    http://www.cl.cam.ac.uk/~mgk25/uc­s/examples/UTF-8-demo.txt
  2. 4 Python libraries for building great command-line user interfaces
    https://opensource.com/article/17/5/4-practical-python-libraries
  3. prompt_toolkit 2.0.3 na PyPi
    https://pypi.org/project/prom­pt_toolkit/
  4. python-prompt-toolkit na GitHubu
    https://github.com/jonathan­slenders/python-prompt-toolkit
  5. The GNU Readline Library
    https://tiswww.case.edu/php/chet/re­adline/rltop.html
  6. GNU Readline (Wikipedia)
    https://en.wikipedia.org/wi­ki/GNU_Readline
  7. readline — GNU readline interface (Python 3.x)
    https://docs.python.org/3/li­brary/readline.html
  8. readline — GNU readline interface (Python 2.x)
    https://docs.python.org/2/li­brary/readline.html
  9. GNU Readline Library – command line editing
    https://tiswww.cwru.edu/php/chet/re­adline/readline.html
  10. gnureadline 6.3.8 na PyPi
    https://pypi.org/project/gnureadline/
  11. Editline Library (libedit)
    http://thrysoee.dk/editline/
  12. Comparing Python Command-Line Parsing Libraries – Argparse, Docopt, and Click
    https://realpython.com/comparing-python-command-line-parsing-libraries-argparse-docopt-click/
  13. libedit or editline
    http://www.cs.utah.edu/~bi­gler/code/libedit.html
  14. WinEditLine
    http://mingweditline.sourceforge.net/
  15. rlcompleter — Completion function for GNU readline
    https://docs.python.org/3/li­brary/rlcompleter.html
  16. rlwrap na GitHubu
    https://github.com/hanslub42/rlwrap
  17. rlwrap(1) – Linux man page
    https://linux.die.net/man/1/rlwrap
  18. readline(3) – Linux man page
    https://linux.die.net/man/3/readline
  19. history(3) – Linux man page
    https://linux.die.net/man/3/history
  20. vi(1) – Linux man page
    https://linux.die.net/man/1/vi
  21. emacs(1) – Linux man page
    https://linux.die.net/man/1/emacs
  22. Pygments – Python syntax highlighter
    http://pygments.org/
  23. Write your own lexer
    http://pygments.org/docs/le­xerdevelopment/
  24. Jazyky podporované knihovnou Pygments
    http://pygments.org/languages/
  25. Pygments FAQ
    http://pygments.org/faq/
  26. TUI – Text User Interface
    https://en.wikipedia.org/wiki/Text-based_user_interface
  27. PuDB: výkonný debugger pro Python s retro uživatelským rozhraním (nástroj s plnohodnotným TUI)
    https://www.root.cz/clanky/pudb-vykonny-debugger-pro-python-s-retro-uzivatelskym-rozhranim/
  28. Historie vývoje textových editorů: krkolomná cesta k moderním textovým procesorům
    https://www.root.cz/clanky/historie-vyvoje-textovych-editoru-krkolomna-cesta-k-modernim-textovym-procesorum/
  29. Rosetta Code
    http://rosettacode.org/wi­ki/Rosetta_Code
  30. Mandelbrot set: Sinclair ZX81 BASIC
    http://rosettacode.org/wi­ki/Mandelbrot_set#Sinclair_ZX81_BA­SIC
  31. Nástroj Dialog
    http://invisible-island.net/dialog/
  32. Projekt Zenity
    https://wiki.gnome.org/Pro­jects/Zenity
  33. Xterm256 color names for console Vim
    http://vim.wikia.com/wiki/Xter­m256_color_names_for_conso­le_Vim
Našli jste v článku chybu?