Library Documentation
In addition to the easy to use command-line script, you can also write programs using the purdy library. The purdy command-line script uses this library to display a simple file to the screen.
Example Program
# reads 'my_code.py' and displays it to the screen with line numbers
from purdy.tui import AppFactory, Code
# An app is the entry to showing content. The AppFactory has convenience
# methods for creating an app.
app = AppFactory.simple(line_number=1)
# A `CodeBox` object is what displays your content to the screen. A simple
# app has one of these called `box`
box = app.box
# Read a file and parse it using the `Code` object
code = Code('my_code.py')
# You perform actions on the `CodeBox` by chaining calls. These calls
# effect how things are presented.
(box
.append(code)
.set_numbers(1)
)
# Purdy is a Textual app, so you run it like you would any Textual program
app.run()
Purdy is a Textual app, and the purdy.tui.apps.AppFactory is a
convenient way to to create an app instance. Inside the app, you can have one
or more purdy.tui.codebox.CodeBox objects that display contents. The
purdy.tui.apps.AppFactory.simple() call creates a single CodeBox that
fills the screen. purdy.tui.apps.AppFactory.split() creates a screen
with two boxes one above the other.
You put content in a CodeBox using a purdy.content.Code object. The
Code object constructor takes the name of a file to read. By default it
attempts to detect what kind of content is in the file based on the file
extension. There is a long list of extensions supported, each providing their
own syntax highlighting. The three most common are .py for Python files,
.repl for text captures of a Python REPL session, and .con for Bash shell
sessions. A full list of supported file names can be found by running the
purdy command without arguments.
The Code object also has a purdy.content.Code.text() method that can
be used as a factory that parses a string. This method assumes the string
contains Python code, but you can use the lexer argument to specify other
kinds of content.
In addition to adding Code objects to the CodeBox, you can also add text
in the form of Textual Markup. If you only want
plain text, the purdy.tui.tui_content.EscapeText wrapper escapes the
Textual Markup.
Once you have created an app, you access its CodeBox objects and perform
actions on them. Actions change what you see on the screen. Two common actions
are purdy.tui.codebox.CodeBox.append() which appends text to the box, and
purdy.tui.codebox.CodeBox.typewriter() which animations typing of the
content. If the content type being animated represents an interactive console,
the typewriter animation will wait at each prompt, allowing you to control the
pace of the animation. In Python, >>> and … are considered prompts, and
in Bash anything starting with $ is one.
Actions all return an instance of the CodeBox that called them, so can be chained together.
View more examples in the Sample Code section.
Library API
- class purdy.tui.apps.AppFactory
Factory methods for creating a purdy app.
- classmethod full(row_specs, max_height=None)
Creates a TUI screen based on a list of rows, where each row is a list of
BoxSpecclasses.- Parameters:
- classmethod simple(max_height=None, line_number=None, auto_scroll=False, title=None)
Creates a purdy display with a single
CodeBoxinside of it.- Parameters:
max_height – limit the height of the content in the terminal, defaults to None
line_number – specify a starting line number for the code box, defaults to None
auto_scroll – when True, if content is added to the code box it scrolls to the bottom. Defaults to False.
title – a title to include at the top of the
purdy.tui.codebox.CodeBox, defaults to None
- classmethod split(max_height=None, line_number_top=None, auto_scroll_top=False, relative_height_top=1, line_number_bottom=None, auto_scroll_bottom=False, relative_height_bottom=1, top_title=None, bottom_title=None)
Creates a purdy display with two
CodeBoxobjects one on top of the other.- Parameters:
max_height – limit the height of the content in the terminal, defaults to None
line_number_top – specify a starting line number for the top code box, defaults to None
auto_scroll_top – when True, if content is added to the top code box it scrolls to the bottom. Defaults to False.
relative_height_top – specify the height of the top code box against the bottom one. For example top=1, bottom=1 makes them the same size, top=3, bottom=1, makes them be 3/4 and 1/4 of the screen respectively
line_number_bottom – specify a starting line number for the bottom code box, defaults to None
auto_scroll_bottom – when True, if content is added to the bottom code box it scrolls to the bottom. Defaults to False.
relative_height_bottom – specify the height of the bottom code box against the top one.
top_title – a title to include over the top
CodeBox, defaults to Nonebottom_title – a title to include over the bottom
CodeBox, defaults to None
- class purdy.content.Code(filename, lexer='detect', theme=None)
Encapsulates
CodeLineobjects to track lines of code and any associated style information.Constructor reads code from a file, build an associated parser, and add the resulting lines to this object.
Warning
Files must be in UTF-8 format
- Parameters:
filename – Name of file to read of pathlib.Path object
lexer – Identifier that determines which
LexerSpecto use when parsing the code. Defaults to “detect”theme – Either a string containing the base name of a theme (without the category type like code, con, etc) or a
Themeobject. Defaults to None in which case it uses the class attribute default_theme_name as the theme name.
- chunk(amount)
This method is for doing iterator-like access to the
Codeobject. Each call returns a copy of the object containing a subset of lines, with each subsequent call returning the next subset. To reset to the beginning, set Code.current to 0.
- fold(index, length)
Create a fold in the code
- Parameters:
index – Index number to start the fold at
length – how many lines to include in the fold
- highlight(*args)
Turn highlighting on for one or more code lines. Each argument can be an int (index value, supports negative indexing), a tuple (specifying starting line and number of lines to highlight, start line can be negative), a string specifying a range (“1-3” highlights lines 1 through 3 inclusive), or a partial highlight.
There are two kinds of highlighting for part of a line. The first is specified by a line number, a colon, a starting character position and a length. Example “3:15,5” highlights characters 15-20 on index line 3. The line number indicator supports negative indexing.
The second is for highlighting an argument in a function call or declaration. Example “3:arg:0” highlights the first argument on line three. The parsing of arguments is very naive, it simply looks for open parenthesis and commas to separate arguments. If your line has tuples or other things that would break that, use partial highlighting with start and length indexes.
# Example code.highlight( 3, # highlight fourth line -1, # last line "5-7" # lines 5 through 7, inclusive "10:20,5" # line 10, characters 20 through 25 "12:arg:3" # line 12, highlight the 4th argument )
All start positions are zero indexed.
- highlight_all_off()
Removes all highlighting
- highlight_off(*args)
Turns highlighting for one or more code lines. See
Code.highlight()for a list of available highlight specifiers
- remaining_chunk()
Associated with the
Code.chunk()call, but returns whatever is left in the block.- Returns:
A copy of this
Codeobject but containing the lines remaining in the chunkification process
- render_line(render_state, line, line_index)
Responsible for rendering the given line and appending the result into the
RenderStateobject.
- reset_metadata()
Sets all the style metadata back to defaults. Mostly used for testing.
- spawn()
Returns a new
Codeobject with the same parser and theme as this one, but empty of any code lines.
- classmethod text(text, lexer='py', theme=None)
Factory method for reading code from a string instead of a file.
- Parameters:
text – Text to parse
lexer – Identifier that determines which
LexerSpecto use when parsing the code. Defaults to “detect”
- unfold(index)
Removes a previously created fold that starts on the given index line.
- class purdy.content.PyText(filename)
Container for text that is valid Python. Useful for doing pre-processing on source code before creating a
Codeobject. Source text is stored in the .content attribute as a string.Warning
Files must be in UTF-8 format
- Parameters:
filename – name of file containing the Python you want to handle
- get_part(name, header=None)
Returns a new
PyTextobject containing just the named part of the original. Parts can be a function, class, or assigned variable.Warning
If the named item is not found your source will be empty!
- Parameters:
name – dot notated name of a function or class. Examples: Foo.bar would find the bar method of class Foo or an inner function named bar in a function named Foo
header – optionally include another part of the source file before the parsed content. Typically used to include the header portion of a file. If given an integer, it will include the first X number of lines. If given a tuple “(x, y)” does a slice on the code with those values
- left_justify()
Returns a new
PyTextobject, having removed a consistent amount of leading whitespace from the front of each line from the original so that at least one line is left-justified.Warning
will not work with mixed tabs and spaces
- remove_double_blanks(trim_whitespace=True)
Returns a new
PyTextobject with any two blank lines in a row removed. If trim_whitespace is True (default) a line with only whitespace is considered blank, otherwise it only looks for n- Parameters:
trim_whitespace – when True, treat whitespace as a blank line
- classmethod text(content)
Factory method based on text passed in instead of reading from a file.
- Parameters:
content – the Python source code for this object
- class purdy.themes.Theme(full_name, colour_map, inherit=None)
Encapsulates colourization theme information. Uses a dictionary mapping Pygments tokens to a colour code.
- class purdy.tui.codebox.BoxSpec(width: int, line_number: int = None, auto_scroll: bool = False, border: str = '', title: str = '')
Used to describe each text area in the app that will be showing code.
- Parameters:
width – relative width based on other boxes in the row. For example, row_specs=[Box_Spec(2), BoxSpec(1)] results in a single row where the first box takes up 2/3rds of the space.
line_number – Starting line number for code displayed in the box. Defaults to None
auto_scroll – True to scroll down when content gets added
border – A string specifying which borders are on for this box. Expects the letters “t”, “b”, “l”, “r” in any order for turning on the top, bottom, left, and right borders respectively. Defaults to no borders.
- class purdy.tui.codebox.CodeBox(id, row_spec, box_spec)
Contains and controls content to be displayed to the screen. Wraps the display widget and includes the action methods for the purdy animations.
- append(content)
Action: appends content to the
CodeBox- Parameters:
content – Textual Markup,
EscapeText, or aCodeobject- Returns:
this
CodeBoxso action calls can be chained
- highlight(*args, section_index=None)
Action: issue highlight commands to a
Codeblock. See inside of thisCodeBox. Seehighlight()for details on highlight specifiers.- Parameters:
args – series of highlight specifiers
section_indicator – Each thing added to the
CodeBoxis considered a section. This argument specifies the index of the section to apply the highlighting to. Defaults to None, meaning use the last section. It is up to you to make sure the section is the kind that supports highlighting.
- highlight_all_off()
Action: remove highlighting from all
Codesections within thisCodeBox- Returns:
this
CodeBoxso action calls can be chained
- highlight_chain(*args, section_index=None)
Action: Issue a series of highlight commands in sequence. Highlights the first, waits, turns it off, then highlights the next. Only works with
Codeblocks. Seehighlight()for details on highlight specifiers.- Parameters:
args – series of highlight specifiers. Each argument can also be a list to activate a set of highlight specifiers together
section_indicator – Each thing added to the
CodeBoxis considered a section. This argument specifies the index of the section to apply the highlighting to. Defaults to None, meaning use the last section. It is up to you to make sure the section is the kind that supports highlighting.
- Returns:
this
CodeBoxso action calls can be chained
- highlight_off(*args, section_index=None)
Issue highlight_off commands to a
Codeblock. Seehighlight_off()for details on highlight specifiers.- Parameters:
args – series of highlight specifiers. Each argument can also be a list to deactivate a set of highlight specifiers together
section_indicator – The index number of the section to apply the highlighting to. Defaults to None, meaning use the last section. It is up to you to make sure the section is the kind that supports highlighting.
- Returns:
this
CodeBoxso action calls can be chained
- move_by(amount)
Action: scrolls this
CodeBoxby the given amount- Parameters:
amount – number of characters to scroll down, supports negative numbers for scrolling up
- Returns:
this
CodeBoxso action calls can be chained
- pause(pause, pause_variance=None)
Action: pause before next animation
- Parameters:
pause – seconds to pause for
pause_variance – random amount to vary the pause by, defaults to None
- Returns:
this
CodeBoxso action calls can be chained
- prompt(prompt, answer, animate_answer=True, delay=0.13, delay_variance=0.03)
Appends two pieces of Textual markup into the
CodeBox, first the prompt value, then waits, then animates the typing of the answer value. The answer appears on the same line as the prompt unless you explicitly include a newline.Warning
This method only accepts Textual markup. It does not support EscapedText. Text with markup characters will need to be escaped manually
- Parameters:
prompt – text to prompt with
answer – the answer to append
animate_answer – when True (default) use a typewriter animation for the answer
delay – Length of time to sleep between characters. Defaults to 0.13 seconds
delay_variance – amount of random variability in the typing delay. Defaults to 0.03 seconds
- Returns:
this
CodeBoxso action calls can be chained
- replace(content)
Action: replaces the content in this
CodeBoxwith that provided- Parameters:
content – Textual Markup,
EscapeText, or aCodeobject- Returns:
this
CodeBoxso action calls can be chained
- set_numbers(starting_num)
Action: turn line numbering on for this
CodeBox- Parameters:
starting_num – value to start the numbering with
- Returns:
this
CodeBoxso action calls can be chained
- text_typewriter(content, delay=0.13, delay_variance=0.03)
Action: performs a typing animation on Textual Markup or
EscapeText.- Parameters:
content – Content to animate
delay – Length of time to sleep between characters. Defaults to 0.13 seconds
delay_variance – amount of random variability in the typing delay. Defaults to 0.03 seconds
- Returns:
this
CodeBoxso action calls can be chained
- transition(content=None, speed=1)
Action: performs a transition wipe animation then replaces the content in this
CodeBoxwith that provided- Parameters:
content – Textual Markup,
EscapeText, or aCodeobject- Returns:
this
CodeBoxso action calls can be chained
- typewriter(code, skip_comments=True, skip_whitespace=True, delay=0.13, delay_variance=0.03, prompt_wait=False)
Action: performs a typing animation with the content in given
Codeobject. Note that unlike most actions this one does not support Textual Markup, useCodeBox.text_typewriter()for that instead.- Parameters:
code –
Codecontent to animateskip_comments – When True (default) a comment is animated as a single item instead of typing it
skip_whitespace – When True (default) any block of whitespace is treated as a single item instead of each character within it
delay – Length of time to sleep between characters. Defaults to 0.13 seconds
delay_variance – amount of random variability in the typing delay. Defaults to 0.03 seconds
prompt_wait – When True, pause for interaction when at the end of a line beginning with prompt
- Returns:
this
CodeBoxso action calls can be chained
- update(content, ignore_auto_scroll=False)
Updates the content of the widget, typically shouldn’t be called directly.
- class purdy.tui.codebox.RowSpec(height: int, boxes: list)
Container for a row of
BoxSpecobjects to describe a row in the display grid.- Parameters:
height – relative height of this row in comparison to others in the grid. For example [RowSpec(2, …), RowSpec(1,…)] produces two rows with the first taking up 2/3rds of the height of the screen.
boxes – a list of
BoxSpecobjects in this row