Example #1
0
    def setup_method(self):
        with mock.patch("lira.app.CONFIG_FILE", config_file):
            self.app = LiraApp()
            self.app.setup()

        self.tui = mock.MagicMock()
        self.tui.lira = self.app
Example #2
0
    def __init__(self):
        self.lira = LiraApp()
        self.lira.setup()

        self.content = ContentArea(self)
        self.status = StatusBar(self)

        self.menu = SidebarMenu(self)
        self.menu.reset(BooksList(self))

        self.container = HSplit(
            [
                VSplit(
                    [
                        self.menu,
                        self.content,
                    ],
                    padding=Dimension.exact(1),
                    padding_char="│",
                    padding_style=theme["separator"],
                ),
                self.status,
            ],
            padding=Dimension.exact(1),
            padding_char="─",
            padding_style=theme["separator"],
        )
        self.app = Application(
            layout=Layout(self.container),
            key_bindings=self.get_key_bindings(),
            mouse_support=True,
            full_screen=True,
            style=style,
            after_render=self._ready,
        )
Example #3
0
    def test_load_default_config(self):
        app = LiraApp()
        app.setup()

        default_config = {
            "books": ["lira.books.intro"],
        }
        assert not non_existing_config.exists()
        assert default_config == app.config
Example #4
0
    def run(self):
        lira = LiraApp()
        lira.setup()

        self.app = Application(
            layout=Layout(self.container),
            key_bindings=get_key_bindings(),
            mouse_support=True,
            full_screen=True,
        )

        self.app.run()
Example #5
0
    def test_load_books(self):
        app = LiraApp()
        app.setup()

        books = app.books
        assert len(books) == 2

        book_a, book_b = books
        book_a.parse()
        book_b.parse()

        assert book_a.metadata["title"] == "Intro to Lira"
        book_path = data_dir / "../../lira/books/intro"
        assert book_a.root == book_path.resolve()

        assert book_b.metadata["title"] == "Basic Introduction to Python"
        book_path = data_dir / "books/example"
        assert book_b.root == book_path
Example #6
0
    def test_ignore_invalid_books(self, read_config):
        read_config.return_value = {
            "books": [
                "lira.not.found.module",
                "/lira/not/found/path",
                "lira/not/found/path",
                "lira.books.intro",
            ],
        }

        app = LiraApp()
        app.setup()

        books = app.books
        assert len(books) == 1
        book = books[0]
        book.parse()
        assert book.metadata["title"] == "Intro to Lira"
Example #7
0
class TestLiraLists:
    def setup_method(self):
        with mock.patch("lira.app.CONFIG_FILE", config_file):
            self.app = LiraApp()
            self.app.setup()

        self.tui = mock.MagicMock()
        self.tui.lira = self.app

    def test_book_list(self):
        books_list = BooksList(tui=self.tui)
        list = books_list.container

        assert list.title_window.text == "Books"
        expected = dedent("""
            Intro to Lira
            Basic Introduction to Python
            """).strip()
        assert to_text(list.list_window) == expected

        assert books_list._get_bullet(0) == "• "

        # Changing focus updates the content window.
        list.next()
        self.tui.content.reset.assert_called_once()

        # Selecting an item updates the list.
        list.select(0)
        self.tui.menu.push.assert_called_once()

    def test_book_chapters_list(self):
        book = self.app.books[1]
        book.parse()
        chapters_list = BookChaptersList(tui=self.tui, book=book)
        list = chapters_list.container

        assert list.title_window.text == "Basic Introduction to Python"
        expected = dedent("""
            Introduction
            Nested Content
            """).strip()
        assert to_text(list.list_window) == expected

        assert chapters_list._get_bullet(0) == "1. "

        # Selecting an item updates the list.
        list.select(0)
        self.tui.menu.push.assert_called_once()

    def test_chapter_sections_list(self):
        book = self.app.books[1]
        book.parse()
        chapter = book.chapters[0]
        chapter.parse()

        sections_list = ChapterSectionsList(tui=self.tui,
                                            chapter=chapter,
                                            index=0)
        list = sections_list.container

        # The first section is rendered by default.
        assert list.title_window.text == "Basic Introduction to Python > Introduction"
        expected = dedent("""
            Comments
            """).strip()
        assert to_text(list.list_window) == expected
        self.tui.content.render_section.assert_called_once()

        assert sections_list._get_bullet(0) == "1.1. "
        assert sections_list._get_bullet(1) == "1.2. "

        # Selecting an item updates the content.
        self.tui.reset_mock()
        list.select(0)
        self.tui.content.render_section.assert_called_once()
Example #8
0
class TerminalUI:
    def __init__(self):
        self.lira = LiraApp()
        self.lira.setup()

        self.content = ContentArea(self)
        self.status = StatusBar(self)

        self.menu = SidebarMenu(self)
        self.menu.reset(BooksList(self))

        self.container = HSplit(
            [
                VSplit(
                    [
                        self.menu,
                        self.content,
                    ],
                    padding=Dimension.exact(1),
                    padding_char="│",
                    padding_style=theme["separator"],
                ),
                self.status,
            ],
            padding=Dimension.exact(1),
            padding_char="─",
            padding_style=theme["separator"],
        )
        self.app = Application(
            layout=Layout(self.container),
            key_bindings=self.get_key_bindings(),
            mouse_support=True,
            full_screen=True,
            style=style,
            after_render=self._ready,
        )

    def get_key_bindings(self):
        keys = KeyBindings()

        @keys.add(Keys.Tab)
        def _(event):
            focus_next(event)

        @keys.add(Keys.BackTab)
        def _(event):
            focus_previous(event)

        @keys.add(Keys.ControlC)
        @keys.add(Keys.ControlQ)
        def _(event):
            exit_app()

        return keys

    def _ready(self, app):
        key = "__is_ready"
        if not hasattr(self, key):
            set_title()
            self.status.notify("Ready!")
            setattr(self, key, True)

    def run(self):
        self.app.run()