lookatme

lookatme is an interactive, terminal-based markdown presentation tool that supports:

  • Themes
  • Syntax highlighting
  • Styling and settings embedded within the Markdown YAML header
  • Embedded terminals as part of a presentation
  • Live and manual source reloading
  • Contrib extensions

Tour

Tour Gif

TL;DR Getting Started

Install lookatme with:

pip install lookatme

Run lookatme on slides written in Markdown:

lookatme slides.md

Slides are separated with --- hrules:

# Slide 1

Some text

---

# Slide 2

More text

A basic, optional YAML header may be included at the top of the slides:

---
title: Slides Presentation
author: Me Not You
date: 2019-12-02
---

# Slide 1

Some text

Getting Started

Installation

lookatme can be installed with pip using the command:

pip install lookatme

Usage

The lookatme CLI has a few options to control it’s behavior:

Usage: lookatme [OPTIONS] [INPUT_FILE]

  lookatme - An interactive, terminal-based markdown presentation tool.

Options:
  --debug
  -l, --log PATH
  -t, --theme [dark|light]
  -s, --style [default|emacs|friendly|colorful|autumn|murphy|manni|monokai|perldoc|pastie|borland|trac|native|fruity|bw|vim|vs|tango|rrt|xcode|igor|paraiso-light|paraiso-dark|lovelace|algol|algol_nu|arduino|rainbow_dash|abap|solarized-dark|solarized-light|sas|stata|stata-light|stata-dark]
  --dump-styles                   Dump the resolved styles that will be used
                                  with the presentation to stdout
  --live, --live-reload           Watch the input filename for modifications
                                  and automatically reload
  --help                          Show this message and exit.
--live / --live-reload

This flag turns on live reloading within lookatme. If the input markdown is a filepath (and not stdin), the filepath with be watched for changes to its modification time. If a change to the file’s modification time is observed, the slide deck is re-read and rendered, keeping the current slide in focus.

If your editor supports saving with every keystroke, instant slide updates are possible:

Live Updates
--debug and --log

Turns on debug logging for lookatme. The debug log will be created in your platform’s temporary directory by default and will be named lookatme.log:

$> lookatme slides.md --debug

# in another terminal
$> tail -f /tmp/lookatme.log
DEBUG:lookatme.RENDER:  Rendering token {'type': 'heading', 'level': 2, 'text': 'TOC'}
DEBUG:lookatme.RENDER:  Rendering token {'type': 'list_start', 'ordered': False}
DEBUG:lookatme.RENDER:    Rendering token {'type': 'list_item_start'}
DEBUG:lookatme.RENDER:      Rendering token {'type': 'text', 'text': '[Features](#features)'}
DEBUG:lookatme.RENDER:      Rendering token {'type': 'list_start', 'ordered': False}
DEBUG:lookatme.RENDER:        Rendering token {'type': 'list_item_start'}

You may set a custom log location with the --log flag

--theme

Themes in lookatme are pre-defined stylings. Lookatme comes with two built-in themes: dark and light. These themes are intended to look good on dark terminals and light terminals.

See the Dark Theme and Light Theme pages for more details. See the Style Precedence page for details on the order style overrides and settings are applied.

--style

This option overrides the Pygments syntax highlighting style to use. See the Style Precedence for details about style overriding order.

At the time of this writing, available Pygments style options include:

  • default
  • emacs
  • friendly
  • colorful
  • autumn
  • murphy
  • manni
  • monokai
  • perldoc
  • pastie
  • borland
  • trac
  • native
  • fruity
  • bw
  • vim
  • vs
  • tango
  • rrt
  • xcode
  • igor
  • paraiso-light
  • paraiso-dark
  • lovelace
  • algol
  • algol_nu
  • arduino
  • rainbow_dash
  • abap
  • solarized-dark
  • solarized-light
  • sas
  • stata
  • stata-light
  • stata-dark
--dump-styles

Print the final, resolved style definition that will be used to render the markdown as currently specified on the command-line. See the Style Precedence section for details on how this works.

E.g.:

lookatme examples/tour.md -theme --style solarized-dark --dump-styles

Slides

Slides in lookatme are:

  • Separated by hrule elements: --- in Markdown
  • Resized to fit the current window

Metadata

Slide metadata is contained within an optional YAML header:

---
title: TITLE
author: AUTHOR
date: 2019-12-02
extensions: []
styles: {}
---
Extensions

Extensions are lookatme contrib modules that redefine lookatme behavior. E.g., the lookatmecontrib.calendar example in the examples folder redefines the render_code function found in lookatme/render/markdown_block.py.

The original render_code function gives contrib extensions first-chance at handling any function calls. Contrib extensions are able to ignore function calls, and thus allow the default lookatme behavior, by raising the IgnoredByContrib exception:

import datetime
import calendar
import urwid


from lookatme.exceptions import IgnoredByContrib


def render_code(token, body, stack, loop):
    lang = token["lang"] or ""
    if lang != "calendar":
        raise IgnoredByContrib()

    today = datetime.datetime.utcnow()
    return urwid.Text(calendar.month(today.year, today.month))
Styles

In addition to the --style and --theme CLI options for lookatme, the slide metadata may explicitly override styling behaviors within lookatme:

---
title: TITLE
author: AUTHOR
date: 2019-12-02
styles:
  style: monokai
  table:
    column_spacing: 3
    header_divider: "-"
---

# Slide 1

text

The final, resolved styling settings that will be used when displaying a markdown source is viewable by adding the --dump-styles flag as a command-line argument.

See the Default Style Settings for a full list of available, overrideable styles.

Dark Theme

The dark theme is intended to appear well on terminals with dark backgrounds

Dark Theme 1 Dark Theme 2 Dark Theme 2

Light Theme

The light theme is intended to appear well on terminals with light backgrounds

Light Theme 1 Light Theme 2 Light Theme 2

Style Precedence

Styling may be set in three locations in lookatme:

  1. In a theme
  2. In a slide’s YAML header
  3. On the command-line

When constructing the final, resolved style set that will be used to render markdown, lookatme starts with the default style settings defined in lookatme.schemas, and then applies overrides in the order specified above.

Overrides are applied by performing a deep merge of nested dictionaries. For example, if the default styles defined in schemas.py were:

headings:
  "1":
    fg: "#33c,bold"
    bg: "default"
  "2":
    fg: "#222,bold"
    bg: "default"

… and if the style overrides defined by a theme were:

headings:
  "1":
    bg: "#f00"

… and if the style overrides defined in the slide YAML header were:

headings:
  "2":
    fg: "#f00,bold,underline"

The final, resolved style settings for rendering the markdown would be:

headings:
  "1":
    fg: "#33c,bold"
    bg: "#f00" # from the theme
  "2":
    fg: "#f00,bold,underline" # from the slide YAML header
    bg: "default"

Default Style Settings

The default styles and formats are defined in the marshmallow schemas in lookatme.schemas. The dark theme is an empty theme with no overrides (the defaults are the dark theme):

bullets:
  '1': "•"
  '2': "⁃"
  '3': "◦"
  default: "•"
headings:
  '1':
    bg: default
    fg: '#9fc,bold'
    prefix: "██ "
    suffix: ""
  '2':
    bg: default
    fg: '#1cc,bold'
    prefix: "▓▓▓ "
    suffix: ""
  '3':
    bg: default
    fg: '#29c,bold'
    prefix: "▒▒▒▒ "
    suffix: ""
  '4':
    bg: default
    fg: '#66a,bold'
    prefix: "░░░░░ "
    suffix: ""
  default:
    bg: default
    fg: '#579,bold'
    prefix: "░░░░░ "
    suffix: ""
link:
  bg: default
  fg: '#228,underline'
quote:
  top_corner: "┌"
  bottom_corner: "└"
  side: "╎"
  style:
    bg: default
    fg: italics,#aaa
style: solarized-dark
table:
  column_spacing: 3
  header_divider: "─"

Contrib Extensions

lookatme allows an extension to override and redefine how markdown is rendered. Extensions have first-chance opportunities to handle rendering function calls. Extensions also have the ability to ignore specific rendering function calls and allow original lookatme behavior (or other extensions) to handle the call to that rendering function.

For example, an extension may provide its own implementation of the render function render_table to provide custom table rendering, such as sortable rows, alternating row background colors, etc.

Using Extensions

Extensions are namespace packages within lookatme.contrib. The are used by

  1. Installing the extension with pip install lookatme.contrib.XXX
  2. Adding the extension to the list of extensions required by your slides:
---
title: TITLE
author: AUTHOR
date: 2019-11-01
extensions:
  - XXX
---

# Slide 1

...

Extension Layout

It is highly recommended that you use the lookatme.contrib-template to create new extensions.

Extensions must be a namespaced module within the lookatme.contrib submodule. The basic tree layout for such an extension is below:

examples/calendar_contrib/
├── lookatme
│   └── contrib
│       └── calendar.py
└── setup.py

Notice that there is not an __init__.py file in the contrib path. This is using the implicit namespace package format for creating namespace packages, where an __init__.py is not needed.

Extension setup.py

Below is the setup.py from the examples/calendar_contrib extension:

"""
Setup for lookatme.contrib.calender example
"""


from setuptools import setup, find_namespace_packages
import os


setup(
    name="lookatme.contrib.calendar",
    version="0.0.0",
    description="Adds a calendar code block type",
    author="James Johnson",
    author_email="d0c.s4vage@gmail.com",
    python_requires=">=3.5",
    packages=find_namespace_packages(include=["lookatme.*"]),
)

Overriding Behavior

Any function within lookatme that is decorated with @contrib_first may be overridden by an extension by defining a function of the same name within the extension module.

For example, to override the render_code function that is declared in lookatme in lookatme/render/markdown_block.py, the example calender extension must declare its own function named render_code that accepts the same arguments and provides the same return values as the original function:

"""
Defines a calendar extension that overrides code block rendering if the
language type is calendar
"""


import datetime
import calendar
import urwid


from lookatme.exceptions import IgnoredByContrib


def render_code(token, body, stack, loop):
    lang = token["lang"] or ""
    if lang != "calendar":
        raise IgnoredByContrib()
    
    today = datetime.datetime.utcnow()
    return urwid.Text(calendar.month(today.year, today.month))

Notice how the extension code above raises the IgnoredByContrib exception to allow the default lookatme behavior to occur.

Overrideable Functions

Below is an automatically generated list of all overrideable functions that are present in this release of lookatme. See the lookatme.tui.SlideRenderer.do_render function for details on markdown_block render function arguments and return values.

lookatme

lookatme package

Subpackages
lookatme.contrib package
Submodules
lookatme.contrib.terminal module

This module defines a built-in contrib module that enables terminal embedding within a slide.

lookatme.contrib.terminal.render_code(token, body, stack, loop)[source]
lookatme.contrib.terminal.shutdown()[source]
Module contents

This module handles loading and using lookatme_contriba modules

Contrib modules are directly used

lookatme.contrib.contrib_first(fn)[source]

A decorator that allows contrib modules to override default behavior of lookatme. E.g., a contrib module may override how a table is displayed to enable sorting, or enable displaying images rendered with ANSII color codes and box drawing characters, etc.

Contrib modules may ignore chances to override default behavior by raising the lookatme.contrib.IgnoredByContrib exception.

lookatme.contrib.load_contribs(contrib_names)[source]

Load all contrib modules specified by contrib_names. These should all be namespaced packages under the lookatmecontrib namespace. E.g. lookatmecontrib.calendar would be an extension provided by a contrib module, and would be added to an extensions list in a slide’s YAML header as calendar.

lookatme.contrib.shutdown_contribs()[source]

Call the shutdown function on all contrib modules

lookatme.render package
Submodules
lookatme.render.asciinema module
lookatme.render.markdown_block module

Defines render functions that render lexed markdown block tokens into urwid representations

lookatme.render.markdown_block.render_block_quote_end(token, body, stack, loop)[source]

Pops the block quote start urwid.Pile() from the stack, taking future renderings out of the block quote styling.

See lookatme.tui.SlideRenderer.do_render for additional argument and return value descriptions.

lookatme.render.markdown_block.render_block_quote_start(token, body, stack, loop)[source]

Begins rendering of a block quote. Pushes a new urwid.Pile() to the stack that is indented, has styling applied, and has the quote markers on the left.

This function makes use of the styles:

quote:
  top_corner: "┌"
  bottom_corner: "└"
  side: "╎"
  style:
    bg: default
    fg: italics,#aaa

See lookatme.tui.SlideRenderer.do_render for additional argument and return value descriptions.

lookatme.render.markdown_block.render_code(token, body, stack, loop)[source]

Renders a code block using the Pygments library.

See lookatme.tui.SlideRenderer.do_render for additional argument and return value descriptions.

lookatme.render.markdown_block.render_heading(token, body, stack, loop)[source]

Render markdown headings, using the defined styles for the styling and prefix/suffix.

See lookatme.tui.SlideRenderer.do_render for argument and return value descriptions.

Below are the default stylings for headings:

headings:
  '1':
    bg: default
    fg: '#9fc,bold'
    prefix: "██ "
    suffix: ""
  '2':
    bg: default
    fg: '#1cc,bold'
    prefix: "▓▓▓ "
    suffix: ""
  '3':
    bg: default
    fg: '#29c,bold'
    prefix: "▒▒▒▒ "
    suffix: ""
  '4':
    bg: default
    fg: '#66a,bold'
    prefix: "░░░░░ "
    suffix: ""
  default:
    bg: default
    fg: '#579,bold'
    prefix: "░░░░░ "
    suffix: ""
Returns:A list of urwid Widgets or a single urwid Widget
lookatme.render.markdown_block.render_list_end(token, body, stack, loop)[source]

Pops the pushed urwid.Pile() from the stack (decreases indentation)

See lookatme.tui.SlideRenderer.do_render for argument and return value descriptions.

lookatme.render.markdown_block.render_list_item_end(token, body, stack, loop)[source]

Pops the pushed urwid.Pile() from the stack (decreases indentation)

See lookatme.tui.SlideRenderer.do_render for argument and return value descriptions.

lookatme.render.markdown_block.render_list_item_start(token, body, stack, loop)[source]

Render the start of a list item. This function makes use of the styles:

bullets:
  '1': "•"
  '2': "⁃"
  '3': "◦"
  default: "•"

See lookatme.tui.SlideRenderer.do_render for argument and return value descriptions.

lookatme.render.markdown_block.render_list_start(token, body, stack, loop)[source]

Handles the indentation when starting rendering a new list. List items themselves (with the bullets) are rendered by the render_list_item_start function.

See lookatme.tui.SlideRenderer.do_render for argument and return value descriptions.

lookatme.render.markdown_block.render_loose_item_start(token, body, stack, loop)[source]

Render the start of a list item. This function makes use of the styles:

bullets:
  '1': "•"
  '2': "⁃"
  '3': "◦"
  default: "•"

See lookatme.tui.SlideRenderer.do_render for argument and return value descriptions.

lookatme.render.markdown_block.render_paragraph(token, body, stack, loop)[source]

Renders the provided text with additional pre and post paddings.

See lookatme.tui.SlideRenderer.do_render for additional argument and return value descriptions.

lookatme.render.markdown_block.render_table(token, body, stack, loop)[source]

Renders a table using the Table widget.

See lookatme.tui.SlideRenderer.do_render for argument and return value descriptions.

The table widget makes use of the styles below:

table:
  column_spacing: 3
  header_divider: "─"
Returns:A list of urwid Widgets or a single urwid Widget
lookatme.render.markdown_block.render_text(token=None, body=None, stack=None, loop=None, text=None)[source]

Renders raw text. This function uses the inline markdown lexer from mistune with the lookatme.render.markdown_inline render module to render the lexed inline markup to urwid Text markup. The created Text markup is then used to create and return a ClickableText instance.

Many other functions call this function directly, passing in the extra text argument and leaving all other arguments blank.

See lookatme.tui.SlideRenderer.do_render for additional argument and return value descriptions.

lookatme.render.markdown_inline module

Defines render functions that work with mistune’s markdown inline lexer render interface

Renders a URI as a link

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.codespan(text, old_styles)[source]

Renders inline code using the pygments renderer. This function also makes use of the coding style:

style: monokai
Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.double_emphasis(text, old_styles)[source]

Renders double emphasis. Handles both **word** and __word__

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.emphasis(text, old_styles)[source]

Renders double emphasis. Handles both *word* and _word_

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.escape(text)[source]

Renders escapes

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.expanded_styles(fn)[source]
lookatme.render.markdown_inline.footnote_ref(key, index)[source]

Renders a footnote

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.image(link_uri, title, text)[source]

Renders an image as a link. This would be a cool extension to render referenced images as scaled-down ansii pixel blocks.

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.inline_html(text)[source]

Renders inline html as plaintext

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.linebreak()[source]

Renders a line break

Returns:list of urwid Text markup tuples.

Renders a link. This function does a few special things to make the clickable links happen. All text in lookatme is rendered using the ClickableText class. The ClickableText class looks for urwid.AttrSpec instances that are actually LinkIndicatorSpec instances within the Text markup. If an AttrSpec is an instance of LinkIndicator spec in the Text markup, ClickableText knows to handle clicks on that section of the text as a link.

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.placeholder()[source]

The starting point of the rendering. The final result will be this returned list with all inline markdown tokens translated into urwid objects

lookatme.render.markdown_inline.render_no_change(text)[source]

Render inline markdown text with no changes

lookatme.render.markdown_inline.strikethrough(text, old_styles)[source]

Renders strikethrough text (~~text~~)

Returns:list of urwid Text markup tuples.
lookatme.render.markdown_inline.text(text)[source]

Renders plain text (does nothing)

Returns:list of urwid Text markup tuples.
lookatme.render.pygments module

Pygments related rendering

class lookatme.render.pygments.UrwidFormatter(**options)[source]

Bases: pygments.formatter.Formatter

Formatter that returns [(text,attrspec), …], where text is a piece of text, and attrspec is an urwid.AttrSpec

classmethod findclosest(colstr, colors=256)[source]

Takes a hex string and finds the nearest color to it.

Returns a string urwid will recognize.

findclosestattr(fgcolstr=None, bgcolstr=None, othersettings='', colors=256)[source]

Takes two hex colstring (e.g. ‘ff00dd’) and returns the nearest urwid style.

format(tokensource, outfile)[source]

Format tokensource, an iterable of (tokentype, tokenstring) tuples and write it into outfile.

formatgenerator(tokensource)[source]

Takes a token source, and generates (tokenstring, urwid.AttrSpec) pairs

style
lookatme.render.pygments.get_formatter(style_name)[source]
lookatme.render.pygments.get_lexer(lang, default='text')[source]
lookatme.render.pygments.get_style(style_name)[source]
lookatme.render.pygments.render_text(text, lang='text', style_name=None, plain=False)[source]

Render the provided text with the pygments renderer

Module contents
lookatme.themes package
Submodules
lookatme.themes.dark module

Defines styles that should look good on dark backgrounds

lookatme.themes.light module
Module contents

Defines the built-in styles for lookatme

lookatme.themes.ensure_defaults(mod)[source]

Ensure that all required attributes exist within the provided module

lookatme.widgets package
Submodules
lookatme.widgets.clickable_text module

This module contains code for ClickableText

class lookatme.widgets.clickable_text.ClickableText(markup, align='left', wrap='space', layout=None)[source]

Bases: urwid.widget.Text

Allows clickable/changing text to be part of the Text() contents

mouse_event(size, event, button, x, y, focus)[source]

Handle mouse events!

signals = ['click', 'change']
class lookatme.widgets.clickable_text.LinkIndicatorSpec(link_label, link_target, orig_spec)[source]

Bases: urwid.display_common.AttrSpec

Used to track a link within an urwid.Text instance

lookatme.widgets.table module

Defines a basic Table widget for urwid

class lookatme.widgets.table.Table(rows, headers=None, aligns=None)[source]

Bases: urwid.container.Pile

Create a table from a list of headers, alignment values, and rows.

calc_column_maxes()[source]
create_cells(body_rows, modifier=None)[source]

Create the rows for the body, optionally calling a modifier function on each created cell Text. The modifier must accept an urwid.Text object and must return an urwid.Text object.

render(size, focus=False)[source]

Do whatever needs to be done to render the table

set_column_maxes()[source]

Calculate and set the column maxes for this table

signals = ['change']
watch(w)[source]

Watch the provided widget w for changes

Module contents
Submodules
lookatme.config module

Config module for lookatme

lookatme.exceptions module

Exceptions used within lookatme

exception lookatme.exceptions.IgnoredByContrib[source]

Bases: Exception

Raised when a contrib module’s function chooses to ignore the function call.

lookatme.log module

Logging module

lookatme.log.create_log(log_path)[source]

Create a new log that writes to log_path

lookatme.log.create_null_log()[source]

Create a logging object that does nothing

lookatme.parser module

This module defines the parser for the markdown presentation file

class lookatme.parser.Parser[source]

Bases: object

A parser for markdown presentation files

parse(input_data)[source]

Parse the provided input data into a Presentation object

Parameters:input_data (str) – The input markdown presentation to parse
Returns:Presentation
parse_meta(input_data)[source]

Parse the PresentationMeta out of the input data

Parameters:input_data (str) – The input data string
Returns:tuple of (remaining_data, meta)
parse_slides(input_data)[source]

Parse the Slide out of the input data

Parameters:input_data (str) – The input data string
Returns:tuple of (remaining_data, slide)
lookatme.pres module

Defines Presentation specific objects

class lookatme.pres.Presentation(input_stream, theme, style_override=None, live_reload=False)[source]

Bases: object

Defines a presentation

reload(data=None)[source]

Reload this presentation

Parameters:data (str) – The data to render for this slide deck (optional)
reload_watcher()[source]

Watch for changes to the input filename, automatically reloading when the modified time has changed.

run(start_slide=0)[source]

Run the presentation!

lookatme.schemas module

Defines all schemas used in lookatme

class lookatme.schemas.BlockQuoteSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.BulletsSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

class Meta[source]

Bases: object

include = {'1': <fields.String(default='•', attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '10': <fields.String(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '2': <fields.String(default='⁃', attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '3': <fields.String(default='◦', attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '4': <fields.String(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '5': <fields.String(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '6': <fields.String(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '7': <fields.String(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '8': <fields.String(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>, '9': <fields.String(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'invalid': 'Not a valid string.', 'invalid_utf8': 'Not a valid utf-8 string.'})>}
opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.HeadingStyleSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.HeadingsSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

class Meta[source]

Bases: object

include = {'1': <fields.Nested(default={'fg': '#9fc,bold', 'bg': 'default', 'prefix': '██ ', 'suffix': ''}, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'type': 'Invalid type.'})>, '2': <fields.Nested(default={'fg': '#1cc,bold', 'bg': 'default', 'prefix': '▓▓▓ ', 'suffix': ''}, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'type': 'Invalid type.'})>, '3': <fields.Nested(default={'fg': '#29c,bold', 'bg': 'default', 'prefix': '▒▒▒▒ ', 'suffix': ''}, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'type': 'Invalid type.'})>, '4': <fields.Nested(default={'fg': '#559,bold', 'bg': 'default', 'prefix': '░░░░░ ', 'suffix': ''}, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'type': 'Invalid type.'})>, '5': <fields.Nested(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'type': 'Invalid type.'})>, '6': <fields.Nested(default=<marshmallow.missing>, attribute=None, validate=None, required=False, load_only=False, dump_only=False, missing=<marshmallow.missing>, allow_none=False, error_messages={'required': 'Missing data for required field.', 'null': 'Field may not be null.', 'validator_failed': 'Invalid value.', 'type': 'Invalid type.'})>}
opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.MetaSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

The schema for presentation metadata

class Meta[source]

Bases: object

render_module

alias of YamlRender

opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.NoDatesSafeLoader(stream)[source]

Bases: yaml.loader.SafeLoader

classmethod remove_implicit_resolver(tag_to_remove)[source]

Remove implicit resolvers for a particular tag

Takes care not to modify resolvers in super classes.

We want to load datetimes as strings, not dates, because we go on to serialise as json which doesn’t have the advanced types of yaml, and leads to incompatibilities down the track.

yaml_implicit_resolvers = {'': [('tag:yaml.org,2002:null', re.compile('^(?: ~\n |null|Null|NULL\n | )$', re.VERBOSE))], '!': [('tag:yaml.org,2002:yaml', re.compile('^(?:!|&|\\*)$'))], '&': [('tag:yaml.org,2002:yaml', re.compile('^(?:!|&|\\*)$'))], '*': [('tag:yaml.org,2002:yaml', re.compile('^(?:!|&|\\*)$'))], '+': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '-': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '.': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE))], '0': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '1': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '2': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '3': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '4': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '5': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '6': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '7': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '8': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '9': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n |\\.[0-9_]+(?:[eE][-+][0-9]+)?\n |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n |[-+, re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n |[-+]?0[0-7_]+\n |[-+]?(?:0|[1-9][0-9_]*)\n |[-+]?0x[0-9a-fA-F_]+\n |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '<': [('tag:yaml.org,2002:merge', re.compile('^(?:<<)$'))], '=': [('tag:yaml.org,2002:value', re.compile('^(?:=)$'))], 'F': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], 'N': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE)), ('tag:yaml.org,2002:null', re.compile('^(?: ~\n |null|Null|NULL\n | )$', re.VERBOSE))], 'O': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], 'T': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], 'Y': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], 'f': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], 'n': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE)), ('tag:yaml.org,2002:null', re.compile('^(?: ~\n |null|Null|NULL\n | )$', re.VERBOSE))], 'o': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], 't': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], 'y': [('tag:yaml.org,2002:bool', re.compile('^(?:yes|Yes|YES|no|No|NO\n |true|True|TRUE|false|False|FALSE\n |on|On|ON|off|Off|OFF)$', re.VERBOSE))], '~': [('tag:yaml.org,2002:null', re.compile('^(?: ~\n |null|Null|NULL\n | )$', re.VERBOSE))]}
class lookatme.schemas.StyleFieldSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.StyleSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

Styles schema for themes and style overrides within presentations

class Meta[source]

Bases: object

render_module

alias of YamlRender

opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.TableSchema(*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict[KT, VT] = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)[source]

Bases: marshmallow.schema.Schema

opts = <marshmallow.schema.SchemaOpts object>
class lookatme.schemas.YamlRender[source]

Bases: object

dumps()
loads()
lookatme.slide module

Slide info holder

class lookatme.slide.Slide(tokens, md=None, number=0)[source]

Bases: object

This class defines a single slide. It operates on mistune’s lexed tokens from the input markdown

lookatme.tui module

This module defines the text user interface (TUI) for lookatme

class lookatme.tui.MarkdownTui(pres, palette, start_idx=0)[source]

Bases: urwid.container.Frame

keypress(size, key)[source]

Handle keypress events

prep_pres(pres, start_idx=0)[source]

Prepare the presentation for displaying/use

reload()[source]

Reload the input, keeping the current slide in focus

run()[source]
update()[source]
update_body()[source]

Render the provided slide body

update_creation()[source]

Update the author and date

update_slide_num()[source]

Update the slide number

update_title()[source]

Update the title

class lookatme.tui.SlideRenderer(loop)[source]

Bases: threading.Thread

daemon = True
do_render(to_render, slide_num)[source]

Perform the actual rendering of a slide. This is done by:

  • parsing the slide into tokens (should have occurred already)
  • iterating through each parsed markdown token
  • calling the appropriately-named render function for the token["type"] in lookatme.render.markdown_block

Each render function must have the signature:

def render_XXX(token, body, stack, loop):
    pass

The arguments to the render function are described below:

  • token - the lexed markdown token - a dictionary
  • body - the current urwid.Pile() that return values will be added to (same as stack[-1])
  • stack - The stack of urwid.Pile() used during rendering. E.g., when rendering nested lists, each nested list will push a new urwid.Pile() to the stack, each wrapped with its own additional indentation.
  • loop - the urwid.MainLoop instance being used by lookatme. This won’t usually be used, but is available if needed.

Main render functions (those defined in markdown_block.py) may have three types of return values:

  • None - nothing is added to stack[-1]. Perhaps the render function only needed to add additional indentation by pushing a new urwid.Pile() to the stack.
  • list(urwid.Widget) - A list of widgets to render. These will automatically be added to the Pile at stack[-1]
  • urwid.Widget - A single widget to render. Will be added to stack[-1] automatically.
flush_cache()[source]

Clea everything out of the queue and the cache.

get_slide(slide_number)[source]

Fetch the slide from the cache

queue_render(slide)[source]

Queue up a slide to be rendered.

render_slide(slide, force=False)[source]

Render a slide, blocking until the slide completes. If force is True, rerender the slide even if it is in the cache.

run()[source]

Run the main render thread

stop()[source]
lookatme.tui.create_tui(pres, start_slide=0)[source]

Run the provided presentation

Parameters:start_slide (int) – 0-based slide index
lookatme.tui.text(style, data, align='left')[source]
lookatme.utils module
lookatme.utils.dict_deep_update(to_update, new_vals)[source]

Deeply update the to_update dict with the new_vals

lookatme.utils.flatten_text(text, new_spec=None)[source]

Return a flattend list of tuples that can be used as the first argument to a new urwid.Text().

Parameters:
  • text (urwid.Text) – The text to flatten
  • new_spec (urwid.AttrSpec) – A new spec to merge with existing styles
Returns:

list of tuples

lookatme.utils.get_fg_bg_styles(style)[source]
lookatme.utils.overwrite_spec(orig_spec, new_spec)[source]
lookatme.utils.pile_add(pile, widgets)[source]
lookatme.utils.resolve_bag_of_text_markup_or_widgets(items)[source]

Resolve the list of items into either contiguous urwid.Text() instances, or pre-existing urwid.Widget objects

lookatme.utils.row_text(rendered_row)[source]

Return all text joined together from the rendered row

lookatme.utils.spec_from_style(styles)[source]

Create an urwid.AttrSpec from a {fg:”“, bg:”“} style dict. If styles is a string, it will be used as the foreground

lookatme.utils.styled_text(text, new_styles, old_styles=None, supplement_style=False)[source]

Return a styled text tuple that can be used within urwid.Text.

Note

If an urwid.Text instance is passed in as the text parameter, alignment values will be lost and must be explicitly re-added by the caller.

lookatme.utils.translate_color(raw_text)[source]
Module contents

Indices and tables