Purdy¶
During talks or screencasts I don’t want to be typing code, it is too error prone and too likely to mess up my speaking flow. Purdy is both a set of programs and a library to display colourized code in a series of animations.
The purdy
command takes one of a Python program, a Python REPL console file
or a Bash console file. Source code is presented to the screen as if typing.
For console files, the typing pauses at a prompt, waiting for interaction.
Prompts are:
>>>
or...
for Python REPL$
for Bash console
If the program is paused at a prompt, pressing the right arrow will continue. Typing animation can be skipped over by pressing the letter “s” instead. Animation can be undone by pressing the left arrow. More info on keys can be found in the help dialog, viewed by pressing “?”.
Example Usage:
$ purdy code-snippet.py
The result looks like this:

Once the code has been displayed, further key presses are ignored. At any time you can press “q” to quit.
Purdy Programs¶
The following programs come with the purdy library:
purdy
– Animated display that looks like a program is being typed to the screen.pat
– “purdy cat”, prints ANSI colourized source.prat
– “purdy RTF cat”, prints colourized source in RTF document format. Particularly useful for copying to a clipboard and pasting full colourized source into a document. On OS X prat <filename> | pbcopy will put the output directly to the clipboard.subpurdy
– Full set of commands to control Purdy. Sub-commands dictate behaviour. Does a variety of code presentation. Includes ANSI, RTF, HTML output as well as the typewriter animations.
More information can be found in the Command Line Program Documentation.
Purdy TUI Controls¶
The following keys help you to control the TUI purdy programs:
?
– Help screen<RIGHT>
– next animation step<LEFT>
– previous animation steps
– go to the next step, skipping any animation
For custom made code using the purdy library, the following controls will also work:
S
– go to the next section, skipping any animation.<TAB>
– focus next window area in a multi Screen display<SHIFT><TAB>
– focus previous window area in a multi Screen display
Additionally the s
, S
, and <LEFT>
commands all support skipping
multiple steps by specifying a number first. For example the sequence 12s
would skip past the next 12 steps.
Purdy Library¶
The purdy
script is fairly simple. You can create more complex animations
by writing programs using the purdy library. Custom programs can have split
screens, highlighting lines, slide transitions and more. More information can
be found in the Library Documentation.
Installation¶
$ pip install purdy
Supports¶
Purdy has been tested with Python 3.7 through 3.11. Terminal control is done with the Urwid library. Parsing and tokenization is done through Pygments. Both libraries are execellent and I’m grateful they’re publically available.
Docs & Source¶
Docs: http://purdy.readthedocs.io/en/latest/
Source: https://github.com/cltrudeau/purdy
Version: 1.10.2
Contents¶
Command Line Program Documentation¶
purdy
Command¶
Displays a highlighted version of python text to the screen as if it is being typed
usage: purdy [-h] [--version] [-l {con,py3,bash,dbash,node}]
[--maxheight MAXHEIGHT] [-c] [-x16] [-d DELAY | -w WPM]
[--variance VARIANCE]
filename
Positional Arguments¶
- filename
Name of file to parse
Named Arguments¶
- --version
show program’s version number and exit
- -l, --lexer
Possible choices: con, py3, bash, dbash, node
Name of lexer to use to parse the file. Choices are: “con” (Python 3 Console), “py3” (Python 3 Source), “bash” (Bash Console), “dbash” (Bash Console with a dollar-sign prompt), “node” (JavaScript Node.js Console). If no choice given, attempts to determine the result automatically. If it cannot detect it, it assumes Python 3.
Default: “detect”
- --maxheight
Sets a maximum screen height for the TUI screen viewer. Ignored if not in TUI mode.
Default: 0
- -c, --continuous
Instead of prentending to type like a human, just dump the file to the screen
Default: False
- -x16
Force 16 colour terminal mode in case 256 is not working to the screen
Default: False
- -d, --delay
Amount of time between each letter when in typewriter mode. Specified in milliseconds. Defaults to 130ms
- -w, --wpm
Number of words per minute that the typing speed should look like
- --variance
To make the typing look more real there is a variance in the delay between keystrokes. This value, in milliseconds is how much to go over or under the delay by. Defaults to +/- 30ms
pat
Command¶
This command prints ANSI colourized versions of a file, parsing the file based on a limited number of pygments lexers. ‘pat’ is part of the ‘purdy’ library. A list of supported lexers is available in the help. If no lexer is specified the library attempts to determine which lexer to use automatically.
usage: pat [-h] [-l {con,py3,bash,dbash,node}] [--version] [--num NUM]
[--highlight HIGHLIGHT]
filename
Positional Arguments¶
- filename
Name of file to parse
Named Arguments¶
- -l, --lexer
Possible choices: con, py3, bash, dbash, node
Name of lexer to use to parse the file. Choices are: “con” (Python 3 Console), “py3” (Python 3 Source), “bash” (Bash Console), “dbash” (Bash Console with a dollar-sign prompt), “node” (JavaScript Node.js Console). If no choice given, attempts to determine the result automatically. If it cannot detect it, it assumes Python 3.
Default: “detect”
- --version
show program’s version number and exit
- --num
Display line numbers with code starting with the value given here
Default: -1
- --highlight, --hl
Highlight certain line numbers when displaying the code. Line numbers are 1-indexed. Multiple lines can be higlighted using a hyphen for range (e.g. 1-4, inclusive) or a comma separated list (e.g. 1-4,7,9 is line 1, 2, 3, 4, 7 and 9).
prat
Command¶
This command prints colourized RTF version of a file, parsing the file based on a limited number of pygments lexers. ‘prat’ is part of the ‘purdy’ library. A list of supported lexers is available in the help. If no lexer is specified the library attempts to determine which lexer to user automatically.
usage: prat [-h] [-l {con,py3,bash,dbash,node}] [--version] [--num NUM]
[--background BACKGROUND] [--highlight HIGHLIGHT]
filename
Positional Arguments¶
- filename
Name of file to parse
Named Arguments¶
- -l, --lexer
Possible choices: con, py3, bash, dbash, node
Name of lexer to use to parse the file. Choices are: “con” (Python 3 Console), “py3” (Python 3 Source), “bash” (Bash Console), “dbash” (Bash Console with a dollar-sign prompt), “node” (JavaScript Node.js Console). If no choice given, attempts to determine the result automatically. If it cannot detect it, it assumes Python 3.
Default: “detect”
- --version
show program’s version number and exit
- --num
Display line numbers with code starting with the value given here
Default: -1
- --background, --bg
Change the background colour of the document. When using the –highlight option, you you should also set a background colour, otherwise the background will turn white due to how RTF supports colouring. Format of the colour is like an HTML colour, e.g. #c1b455, without the leading #
- --highlight, --hl
Highlight certain line numbers when displaying the code. Line numbers are 1-indexed. Multiple lines can be higlighted using a hyphen for range (e.g. 1-4, inclusive) or a comma separated list (e.g. 1-4,7,9 is line 1, 2, 3, 4, 7 and 9).
subpurdy
Command¶
Purdy is a library and set of command line tools for displaying code. You can write your own code to display specific content using the library, or use the subcommands of this program for preset usages. The ‘purdy’ command uses the Urwid library to display a colourized version of your code in the console, and is a wrapper to the subcommand of the same name.
usage: subpurdy [-h] [-l {con,py3,bash,dbash,node}] [--version]
{purdy,tokens,print,html,rtf} ... filename
Positional Arguments¶
- filename
Name of file to parse
Named Arguments¶
- -l, --lexer
Possible choices: con, py3, bash, dbash, node
Name of lexer to use to parse the file. Choices are: “con” (Python 3 Console), “py3” (Python 3 Source), “bash” (Bash Console), “dbash” (Bash Console with a dollar-sign prompt), “node” (JavaScript Node.js Console). If no choice given, attempts to determine the result automatically. If it cannot detect it, it assumes Python 3.
Default: “detect”
- --version
show program’s version number and exit
subcommands¶
- command
Possible choices: purdy, tokens, print, html, rtf
Sub-commands:¶
Display code in a interactive console window. Code is written to the screen as if it is being typed
subpurdy purdy [-h] [-c] [-x16] [-d DELAY | -w WPM] [--variance VARIANCE]
- -c, --continuous
Instead of prentending to type like a human, just dump the file to the screen
Default: False
- -x16
Force 16 colour terminal mode in case 256 is not working to the screen
Default: False
- -d, --delay
Amount of time between each letter when in typewriter mode. Specified in milliseconds. Defaults to 130ms
- -w, --wpm
Number of words per minute that the typing speed should look like
- --variance
To make the typing look more real there is a variance in the delay between keystrokes. This value, in milliseconds is how much to go over or under the delay by. Defaults to +/- 30ms
Prints out each line in a file with the corresponding tokens indented beneath it
subpurdy tokens [-h] [--blackandwhite]
- --blackandwhite, --bw
By default code lines are highlighted using ANSI colour. This flag turns this off.
Default: False
Prints code to screen using colourized ANSI escape sequences
subpurdy print [-h] [--num NUM] [--highlight HIGHLIGHT]
- --num
Display line numbers with code starting with the value given here
Default: -1
- --highlight, --hl
Highlight certain line numbers when displaying the code. Line numbers are 1-indexed. Multiple lines can be higlighted using a hyphen for range (e.g. 1-4, inclusive) or a comma separated list (e.g. 1-4,7,9 is line 1, 2, 3, 4, 7 and 9).
Prints code to screen formatted as an HTML div
subpurdy html [-h] [--num NUM] [--highlight HIGHLIGHT] [--full]
- --num
Display line numbers with code starting with the value given here
Default: -1
- --highlight, --hl
Highlight certain line numbers when displaying the code. Line numbers are 1-indexed. Multiple lines can be higlighted using a hyphen for range (e.g. 1-4, inclusive) or a comma separated list (e.g. 1-4,7,9 is line 1, 2, 3, 4, 7 and 9).
- --full
By default only a snippet of HTML is displayed inside a <div>. This flag produces a full HTML document.
Default: False
Prints code to screen formatted as an RTF document
subpurdy rtf [-h] [--num NUM] [--background BACKGROUND]
[--highlight HIGHLIGHT]
- --num
Display line numbers with code starting with the value given here
Default: -1
- --background, --bg
Change the background colour of the document. When using the –highlight option, you you should also set a background colour, otherwise the background will turn white due to how RTF supports colouring. Format of the colour is like an HTML colour, e.g. #c1b455, without the leading #
- --highlight, --hl
Highlight certain line numbers when displaying the code. Line numbers are 1-indexed. Multiple lines can be higlighted using a hyphen for range (e.g. 1-4, inclusive) or a comma separated list (e.g. 1-4,7,9 is line 1, 2, 3, 4, 7 and 9).
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.actions import Append
from purdy.content import Code
from purdy.ui import SimpleScreen
# Screen is the entry to showing content
screen = SimpleScreen(starting_line_number=1)
# Screen has one display area called "code_box", your actions need access
# to this to write the code
code_box = screen.code_box
# read 'my_code.py' and parse it using the Python 3 lexer
blob = Code('code.py', lexer_name='py3')
# actions are like slides in the slides show that is purdy
actions = [
# append the contents of the blob to the display code box
Append(code_box, blob),
]
# start the display event loop
screen.run(actions)
Every purdy library program needs to create a
Screen
or one of its children. The Screen is what
controls the display. Screen
and its children
provide one or more CodeBox
objects which is a
widget on the screen that displays code. You combine a series of
purdy.ui.actions
to display and alter the code. View more examples in
the Sample Code section.
Library API¶
UI (purdy.ui.py)¶
This module is the entry point for the code viewers. It is a lightweight proxy
to implementation of a screen. Screen implementations are found in
purdy.iscreen
. All programs using the purdy library need to create a
Screen
object or one of its children. The factory in this module
determines which actual implementation is loaded.
- class purdy.ui.CodeBox(starting_line_number=- 1, auto_scroll=True, height=0, compact=False)¶
Specifies a box to contain code.
Screen
uses these to determine widget layout, subsequent actions are done within the context of this box. WhenCodeBox.build()
is called by aScreen
class a widget is built and this box is added to the screen.- Parameters
starting_line_number – -1 means no line numbers, anything larger will be the first line number displayed. Defaults to -1
auto_scroll – When True,
purdy.widgets.CodeBox
created by this specification automatically scrolls to newly added content. Defaults to True.height – Number of lines the row containing this box should be. A value of 0 indicates automatic spacing. Defaults to 0.
compact – if False, the dividing line between this box and the next has a 1-line empty boundary. Parameter is ignored if there is no item after this one in the rows=[] listing. Defaults to False
- class purdy.ui.Screen(settings=None, rows=[], max_height=0)¶
Represents the main UI window for the TUI application. The layout is specified by passing in one or more
CodeBox
orTwinCodeBox
objects to the constructor. Each box will have a correspondingpurdy.widgets.CodeWidget
inside of the UI for displaying code.- Parameters
settings – a settings dictionary object. Defaults to None which uses the default settings dictionary:
settings.settings
rows – a list containing one or more
CodeBox
orTwinCodeBox
definitions, to specify the layout of the screenmax_height – maximum display height in TUI mode, defaults to 0, meaning no max
Example:
from purdy.actions import AppendAll from purdy.content import Code from purdy.ui import Screen, CodeBox, TwinCodeBox screen = Screen(rows=[TwinCodeBox(height=8), CodeBox(auto_scroll=False)]) c1 = Code(contents_filename='c1.py', starting_line_number=1) c2 = Code(contents_filename='c2.py') c3 = Code(contents_filename='c3.py') actions = [ AppendAll(screen.code_boxes[0], c1), AppendAll(screen.code_boxes[1], c2), AppendAll(screen.code_boxes[2], c3), ] screen.run(actions)
The above would produce a screen with two rows, the first row having two
purdy.widgets.CodeWidget
objects side by side, the second having a single one. The top left box would have line numbers turned on, both top boxes are 8 lines tall, and the bottom box has auto scrolling turned off.The screen would be divided like this:
Command Line Parameters
Unless “deactivate_args” is set to True in
purdy.settings
(False by default), Screen will also parse command line arguments. This allows scripts calling the library to change their behaviour with switches.Supported switches are:
–debugsteps Print out the animation steps, grouped by Cell and exit
–export Print out the results of the actions
–exportrtf Print out the results of the actions in RTF format
- run(actions)¶
Calls the main display event loop. Does not return until the UI exits.
- class purdy.ui.SimpleScreen(settings=None, starting_line_number=- 1, auto_scroll=True, max_height=0)¶
Convenience implementation of
Screen
that supports a singleCodeBox
. The code box is available asSimpleScreen.code_box
.- Parameters
settings – a settings dictionary object. Defaults to None which uses the default settings dictionary:
settings.settings
starting_line_number – starting line number for the created code box
auto_scroll – When True, the class:ui.CodeBox automatically scrolls to newly added content. Defaults to True.
max_height – maximum display height in TUI mode, defaults to 0, meaning no max
- class purdy.ui.SplitScreen(settings=None, top_starting_line_number=- 1, top_auto_scroll=True, bottom_starting_line_number=- 1, bottom_auto_scroll=True, top_height=0, compact=False, max_height=0)¶
Convenience implementation of
Screen
that supports twoCodeBox
instances, stacked vertically and separated by a dividing line. The code boxes areSplitScreen.top
andSplitScreen.bottom
.- Parameters
settings – a settings dictionary object. Defaults to None which uses the default settings dictionary:
settings.settings
top_starting_line_number – starting line number for the top code box
top_auto_scroll – When True, the top
ui.CodeBox
automatically scrolls to newly added content. Defaults to True.bottom_starting_line_number – starting line number for the bottom code box
bottom_auto_scroll – When True, the bottom
ui.CodeBox
automatically scrolls to newly added content. Defaults to True.top_height – Number of lines the top box should be. A value of 0 indicates top and bottom should be the same size. Defaults to 0.
compact – True if for the dividing line between the top and bottom screens is to have no margin. Defaults to False
max_height – maximum display height in TUI mode, defaults to 0, meaning no max
- class purdy.ui.TwinCodeBox(left_starting_line_number=- 1, left_auto_scroll=True, left_weight=1, right_starting_line_number=- 1, right_auto_scroll=True, right_weight=1, height=0, compact=False)¶
Specifies two side-by-side CodeBoxes. The contained CodeBoxes can be either accessed as twin.left and twin.right, or twin[0] and twin[1]. When
TwinCodeBox.build()
is called, the widgets are created and added to theScreen.code_boxes
list sequentially, i.e. a single TwinCodeBox results in two CodeBox items in Screen’s list.- Parameters
left_starting_line_number –
right_starting_line_number – -1 to turn line numbers off, any higher value is the first number to display. Defaults to -1
left_auto_scroll –
right_auto_scroll – True to specify that scrolling happens automatically for the left and right boxes created by this spec. Defaults to True.
left_weight –
right_weight – relative weights for the widths of the columns, if the values are the same then the columns are the same width, otherwise the widths are formed based on the ratio of left:right. Example: left_weight=2, right_weight=1 means the left side will be twice the width of the right side. Both values default to 1.
height – number of lines for the row this set of boxes is in. The default of 0 specifies automatic height
compact – if False, the dividing line between this box and the next has a 1-line empty boundary. Parameter is ignored if there is no item after this one in the rows=[] listing. Defaults to False
Content¶
Reperesntations of source code are found in this module.
- class purdy.content.Code(filename='', text='', lexer_name='detect', purdy_lexer=None)¶
Represents source code from the user.
- Parameters
filename – name of a file to read for content. If both this and text is given, filename is used first
text – a string containing code
lexer_name – name of lexer to use to tokenize the code, defaults to ‘detect’, attempting to auto detect the type of content. See
purdy.parser.PurdyLexer
for a list of available lexers.purdy_lexer – if lexer_name is “custom” this parameter is expected to contain a purdy.parser.PurdyLexer object.
- fold_lines(start, end)¶
Call this method to replace one or more lines with a vertical elipses, i.e. a fold of the code.
- Parameters
start – line number of the listing to start code folding on. 1-indexed.
end – line number to fold until, inclusive (1-indexed).
- inline_replace(line_no, pos, content)¶
Replaces the contents of a line starting at pos with the new content
- Parameters
line_no – number of the line to replace, 1-indexed
pos – position number to start the replacement at, 1-indexed
content – content to replace with
- insert_line(line_no, content)¶
Inserts the given line into the source, pushing the content down from the given line number
- Parameters
line_no – number of the line to insert at, 1-indexed
content – content to insert
- left_justify()¶
Removes a consistent amount of leading whitespace from the front of each line so that at least one line is left-justified.
Warning
will not work with mixed tabs and spaces
- python_portion(name)¶
Treates the source in this object as Python and then finds either the named function, class, or assigned variable and replaces the source with only the found item.
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
- remove_double_blanks(trim_whitespace=True)¶
Removes the second of two blanks in a row. If trim_whitespace is True (default) a line with only whitespace is considered blank, otherwise it only looks for n
- remove_lines(line_no, count=1)¶
Removes one or more lines from the source listing.
- Parameters
line_no – number of the line to remove, 1-indexed
count – number of lines to remove, defaults to 1
- replace_line(line_no, content)¶
Replaces the given line with new content
- Parameters
line_no – number of the line to replace, 1-indexed
content – content to replace it with
- subset(start, end)¶
Returns a new Code object containing just the subset of lines identified in this call
- Parameters
start – line number of the listing to start the subset at. 1-indexed
end – line number to finish the subset on, inclusive. 1-indexed.
- Returns
Code object
Actions¶
Library users specify a series of actions that turn into the presentation animations in the Urwid client. An action is similar to a slide in a slide show, except it can both present and change lines of code on the screen.
All purdy library programs have the following basic structure:
screen = Screen(...)
actions = [ ... ]
screen.run(actions)
Each action gets translated into a series of steps defined in the
purdy.animation
module.
- class purdy.actions.Append(code_box, code)¶
Adds the content of a
purdy.content.Code
object to the end of apurdy.ui.CodeBox
.- Parameters
code_box – the
purdy.ui.CodeBox
instance to insert code intocode – a
purdy.content.Code
object containing the source code to insert.
- class purdy.actions.Clear(code_box)¶
Clears the contents of a
purdy.ui.CodeBox
.- Parameters
code_box – the
purdy.ui.CodeBox
instance where the code is to be replaced
- class purdy.actions.Fold(code_box, position, end=- 1)¶
Folds code by replacing one or more lines with a vertical elipses symbol.
- Parameters
code_box – the
purdy.ui.CodeBox
instance to modifyposition – line number to begin the fold at. Position is 1-indexed.
end – line number to finish the folding at, inclusive. A value of -1 can be used to fold to the end of the box. Defaults to -1.
- class purdy.actions.Highlight(code_box, spec, highlight_on)¶
Cause one or more lines of code to have highlighting turned on or off
- Parameters
code_box –
purdy.ui.CodeBox
to perform onspec – either a string containing comma separated and/or hyphen separated integers (e.g. “1,3,7-9”) or a list of integers specifying the lines in the code box to highlight. Line numbers are 1-indexed
highlight_on – True to turn highligthing on, False to turn it off
- class purdy.actions.HighlightChain(code_box, spec_list)¶
A common pattern with highlighting lines is to turn a highlight on for some set of lines, then turn it off and turn it on for more lines. This is a convenience wrapper to the
Highlight
action, turning items on and off in series.- Parameters
code_box –
purdy.ui.CodeBox
to perform series of highlight onspec_list – a list of highlight specs (see
Highlight
for details on a spec)
- class purdy.actions.Insert(code_box, position, code)¶
Inserts the content of a
purdy.content.Code
object to a specified line in apurdy.ui.CodeBox
. Pushes content down, inserting at “1” is the beginning of the list. Position is 1-indexed- Parameters
code_box – the
purdy.ui.CodeBox
instance to insert code intoposition – line number to insert code at. Position is 1-indexed. Content is pushed down, so a value of “1” inserts at the beginning. Negative indicies are supported. A value of “0” will append the code to the bottom.
code – a
purdy.content.Code
object containing the source code to insert.
- class purdy.actions.Remove(code_box, position, size)¶
Removes one or more lines of a
purdy.ui.CodeBox
.- Parameters
code_box – the
purdy.ui.CodeBox
instance where the code is to be replacedposition – line number to replace the code at. Position is 1-indexed. Negative indicies are supported.
size – number of lines to remove.
- class purdy.actions.Replace(code_box, position, code)¶
Replaces one or more lines of a
purdy.ui.CodeBox
using the content of apurdy.content.Code
object. This action attempts to overwrite using the number of lines in thepurdy.content.Code
object passed in, it is up to you to make sure there is enough space in your CodeBox.- Parameters
code_box – the
purdy.ui.CodeBox
instance where the code is to be replacedposition – line number to replace the code at. Position is 1-indexed. Negative indicies are supported.
code – a
purdy.content.Code
object containing the source code to insert.
- class purdy.actions.RunFunction(fn, undo, *args, **kwargs)¶
Calls the function passed in, allowing the execution of code during the playing of actions.
- Parameters
fn – function to be called
undo – function to be called when this Action is undone, can be None
**kwargs (*args,) – any remaining arguments are passed to the functions when they are called
- class purdy.actions.Section¶
Marker for the beginning of a section. In the TUI you can skip to the next section marker using “S”.
- class purdy.actions.Shell(code_box, cmd)¶
Runs a shell command via subprocess. Does not display the command (you’re better off using a typewriter command to show it, then use this to spit out the results). Command and results are added to the
purdy.ui.CodeBox
.- Parameters
code_box – the
purdy.ui.CodeBox
instance where the code is to be appendedcmd – string containing the shell command and its paramters. Example:
ls -la
.
- class purdy.actions.Sleep(time)¶
Causes animations to pause for the given amount of time. Note that this action happens within a cell, so is considered part of the group of animation steps done together. For example if Append + Sleep + Append is part of the same cell it is all done/undone together.
- Parameters
time – Either the amount of time to sleep in seconds (ints and floats supported), or a tuple containing a pair of times specifying the range of a random value to sleep.
- class purdy.actions.StopMovie¶
Causes the presentation
purdy.ui.Screen
to exit movie mode
- class purdy.actions.Suffix(code_box, position, source)¶
Adds the provided text to the end of an existing line in a
purdy.ui.CodeBox
.- Parameters
code_box – the
purdy.ui.CodeBox
instance where the code is to be appendedposition – line number to replace the code at. Position is 1-indexed. Negative indicies are supported.
source – string containing content to append to the line
- class purdy.actions.Transition(code_box, code=None, code_box_to_copy=None)¶
Replaces the contents of a
purdy.ui.CodeBox
with new content, doing a wipe animation from top to bottom. Only one of code or code_box_to_copy should be given, both can be blank to transition to an empty screen.- Parameters
code_box – the
purdy.ui.CodeBox
instance to perform the transition oncode – a
purdy.content.Code
object containing the source code replacing the existing content. Should not be used at the same time as code_box_to_copy parameter.code_box_to_copy – a code box containing rendered code to copy into this one to display. This is typically a
VirtualCodeBox
. Should not be used at the same time as code parameter.
- class purdy.actions.Wait¶
Causes the animations to wait for a right arrow key press before continuing.
Typewriter Actions¶
Typewriter actions display code using a typewriter animation. Code content is
displayed a letter at a time as if someone is typing. The
purdy.settings
module contains default values for typing speeds and
variance time between letters being pressed.
When the code in question is based on a console, the typewriter will wait for
the right arrow to be pressed whenever it sees a prompt. For example, when
appending Python REPL code, the >>>
will cause the interface to wait.
- class purdy.actions.AppendTypewriter(code_box, code)¶
Adds the content of a
purdy.content.Code
object to apurdy.ui.CodeBox
using the typewriter animation.- Parameters
code_box – the
purdy.ui.CodeBox
instance to append code intocode – a
purdy.content.Code
object containing the source code to insert.
- class purdy.actions.InsertTypewriter(code_box, position, code)¶
Inserts the contents of a
purdy.content.Code
object at the given position using the typewriter animation.- Parameters
code_box – the
purdy.ui.CodeBox
instance to append code intoposition – line number to insert the code at. Position is 1-indexed.
code – a
purdy.content.Code
object containing the source code to insert.
- class purdy.actions.SuffixTypewriter(code_box, position, source)¶
Adds the provided text to the end of an existing line in a
purdy.ui.CodeBox
using a typewriter animation.- Parameters
code_box – the
purdy.ui.CodeBox
instance to append code intoposition – line number to insert the code at. Position is 1-indexed. Negative indicies are supported.
source – a string to be appended to the given line
Default Settings¶
- settings.settings¶
"""
Settings (purdy.settings.py)
============================
Defines the default settings for :class:`purdy.ui.Screen` objects, can be
overridden by passing an altered dictionary into the Screen's constructor.
"""
settings = {
# delay between characters appearing on screen (in milliseconds)
'delay':130,
# range of random time in milliseconds to change the delay; makes typing
# look more natural
'delay_variance':30,
# movie mode: instead of waiting for key presses, play like a movie, -1
# disables, otherwise value in milliseconds for delay between played steps
# (like 'delay' field
'movie_mode':-1,
# xterm colour mode, anything but 256 gives 16 colour mode
'colour':256,
# if True, stops Screen from running argparse
'deactivate_args':False,
# max height for presentation, only works in TUI mode, 0 == no max
'max_height':0,
}
Sample Code¶
Here are some examples of scripts using purdy as a library. Full source is available in the repository: https://github.com/cltrudeau/purdy/tree/master/extras/samples
#!/usr/bin/env python
### Example purdy library code
#
# Displays a colourized Python REPL session to the screen
from purdy.actions import Append
from purdy.content import Code
from purdy.ui import SimpleScreen
screen = SimpleScreen()
blob = Code('../display_code/console.repl')
actions = [
Append(screen.code_box, blob),
]
if __name__ == '__main__':
screen.run(actions)
#!/usr/bin/env python
### Example purdy library code
#
# Appends the same colourized Python REPL session to the screen multiple
# times, waiting for a keypress between each
from purdy.actions import Append, Wait
from purdy.content import Code
from purdy.ui import SimpleScreen
screen = SimpleScreen(starting_line_number=1)
code_box = screen.code_box
blob = Code('../display_code/simple.repl')
actions = [
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
Append(code_box, blob),
Wait(),
]
if __name__ == '__main__':
screen.run(actions)
#!/usr/bin/env python
### Example purdy library code
#
# Uses the typewriter animation to display a bash console session
from purdy.actions import AppendTypewriter
from purdy.content import Code
from purdy.ui import SimpleScreen
screen = SimpleScreen()
code_box = screen.code_box
blob = Code('../display_code/curl.bash')
actions = [
AppendTypewriter(code_box, blob),
]
if __name__ == '__main__':
screen.run(actions)
#!/usr/bin/env python
### Example purdy library code
#
# Demonstrates the Shell action that runs a subprocess and returns the result
from purdy.actions import Shell, AppendTypewriter
from purdy.content import Code
from purdy.ui import SimpleScreen
screen = SimpleScreen()
code_box = screen.code_box
cmd1 = 'echo "hello there"'
cmd2 = 'echo "it is a nice day today"'
blob = Code(text=f'$ {cmd1}')
blob2 = Code(text=f'$ {cmd2}')
actions = [
AppendTypewriter(code_box, blob),
Shell(code_box, cmd1),
AppendTypewriter(code_box, blob2),
Shell(code_box, cmd2),
]
if __name__ == '__main__':
screen.run(actions)
#!/usr/bin/env python
### Example purdy library code
#
# Demonstrates the code folding mechanism
from purdy.actions import Append, Fold, Wait, Clear
from purdy.content import Code
from purdy.ui import SimpleScreen
code = Code('../display_code/code.py')
screen = SimpleScreen(starting_line_number=1)
box = screen.code_box
actions = [
Append(box, code),
Wait(),
Fold(box, 20, 23),
Wait(),
Fold(box, 27),
Wait(),
Clear(box), # test long fold without wait, used to crash
Append(box, code),
Fold(box, 2),
]
if __name__ == '__main__':
screen.run(actions)
#!/usr/bin/env python
### Example purdy library code
#
# Demonstrates highlighting and unhighlighting lines of code
from purdy.actions import Append, Highlight, Wait
from purdy.content import Code
from purdy.settings import settings
from purdy.ui import SimpleScreen
#settings['colour'] = 16
screen = SimpleScreen(settings, starting_line_number=1)
code_box = screen.code_box
blob = Code('../display_code/console.repl')
actions = [
Append(code_box, blob),
Wait(),
Highlight(code_box, range(5, 41), True),
Wait(),
Highlight(code_box, '5,6,10-20', False),
]
if __name__ == '__main__':
screen.run(actions)
#!/usr/bin/env python
### Example purdy library code
#
# Demonstrates appending strings to the end of existing lines as well as
# replacing lines. Both done with and without the typewriter animation.
from purdy.actions import (Append, Wait, Suffix, SuffixTypewriter,
Replace, Remove, InsertTypewriter)
from purdy.content import Code
from purdy.ui import SplitScreen
screen = SplitScreen(top_starting_line_number=10)
top = screen.top
bottom = screen.bottom
source = """\
@decorator
def foo(x):
\"\"\"Multi-line
doc string
\"\"\"
for index in range(1, x):
blah = '''
thing'''
# about to print
print(index)
"""
code = Code(text=source)
source = """\
>>> a = 1
>>> b = 2
>>> c = 3
"""
repl = Code(text=source)
actions = [
Append(top, code),
Append(bottom, repl),
Wait(),
Suffix(top, 1, 's'),
Suffix(top, 1, ' # append'),
Suffix(top, 2, ' # append'),
Suffix(top, 3, ' more string now'),
Suffix(top, 5, ' # append'),
Suffix(top, 6, ' # append'),
Suffix(top, 7, ' inside blah mline'),
Suffix(top, 8, ' # append'),
Suffix(top, 9, ' more comment'),
Suffix(top, 10, ' # append'),
Wait(),
SuffixTypewriter(bottom, 2, '9'),
Wait(),
]
blob1 = Code(text='>>> d = 4')
blob2 = Code(text="""\
>>> e = 5
>>> f = 6
""")
actions.extend([
Replace(bottom, 3, blob1),
Wait(),
SuffixTypewriter(bottom, 1, '56789'),
Wait(),
Suffix(bottom, 1, '333'),
SuffixTypewriter(bottom, 1, '444'),
Wait(),
Remove(bottom, 2, 1),
InsertTypewriter(bottom, 2, blob2),
InsertTypewriter(bottom, 0, blob2),
])
if __name__ == '__main__':
screen.run(actions)
#!/usr/bin/env python
### Example purdy library code
#
# Demonstrates the slide transition animation
from purdy.actions import Append, Wait, Transition, Fold
from purdy.content import Code
from purdy.ui import SimpleScreen, VirtualCodeBox
screen = SimpleScreen(starting_line_number=10)
code_box = screen.code_box
blob = Code('../display_code/simple.repl')
blob2 = Code('../display_code/traceback.repl')
blob3 = Code('../display_code/decorator.repl')
vbox = VirtualCodeBox(starting_line_number=20, display_mode='urwid')
# prep vbox for copy
vbox.perform_actions([
Append(vbox, blob3),
Fold(vbox, 2, 2),
])
actions = [
Append(code_box, blob2),
Wait(),
Transition(code_box), # test transition to empty
Append(code_box, blob),
Wait(),
# Test Wait after Transition and code box copy
Transition(code_box, code_box_to_copy=vbox),
Wait(),
Append(code_box, blob2),
]
if __name__ == '__main__':
screen.run(actions)
Implementation¶
This is the documentation for the underlying implementing classes. For the most part you don’t need to understand it if you’re just calling into the purdy library.
Animation Cells¶
A Cell represents an animation used by the
purdy.animation.manager.AnimationManager
. A Cell is responsible for
rendering or undoing work to a purdy.widget.CodeBox
. Animating cells
can partially render then wait for an alarm provided by the manager to continue
rendering.
- class purdy.animation.cell.GroupCell¶
Groups steps together into a bundle that can be rendered or undone together. Implements animation alarms so the manager can do timed call backs into the group and continue rendering.
- purdy.animation.cell.group_steps_into_cells(steps)¶
Actions create multiple steps possibly with cell breaks between them. This method takes a list of steps and returns a list of Cell objects, grouping the steps by break marker
- Parameters
steps – a list of steps
- Returns
a list of Cell objects
Animation Management¶
This module handles the slide rendering animation in the urwid purdy player
Animation Steps¶
An animation is created through a series of steps that are executed together.
A cell.GroupCell
wraps these steps. When the user moves forwards and
backwards through the animations each cell is rendered or undone. This module
- exception purdy.animation.steps.StopMovieException¶
Command Line Tools¶
Several of the command line tools have common arguments and needs. This file defines helper functions so these are defined once.
Colour Module (purdy.colour)¶
Contains classes to convert tokens to colour according to the various supported renderers and palettes.
Parser¶
This contains methods and classes to manage parsing of code
- class purdy.parser.CodePart(token, text)¶
- property text¶
Alias for field number 1
- property token¶
Alias for field number 0
- class purdy.parser.PurdyLexer(name, description, pygments_lexer_cls, is_console, palette)¶
Container for the built-in supported lexers. This class is where the names of the lexers are defined. Current choices are:
‘con’ – Python 3 Console
‘py3’ – Python 3 Source code
‘bash’ – interactive Bash session
‘dbash’ – interactive Bash session using a dollar sign prompt
‘node’ – interactive JavaScript / Node.js session
- purdy.parser.parse_source(source, lexer)¶
Parses blocks of source text, returning a list of
CodeLine
objects.
- purdy.parser.token_ancestor(token, ancestor_list)¶
Tokens are hierarchical, in some situations you need to translate a token into one from a known list, e.g. turning a “Token.Literal.Number.Integer” into a “Number”. This method takes a token and a list of approved ancestors and attempts to make the map. If no ancestor is found then a generic “Token” object is returned
- Parameters
token – token to translate into an approved ancestor
ancestor_list – list of approved ancestor tokens
- purdy.parser.token_is_a(token1, token2)¶
Returns true if token1 is the same type as or a child type of token2
Scribe Module (purdy.scribe.py)¶
Methods for transforming code into different representations on stdout.
- purdy.scribe.print_html(listing, snippet=True)¶
Prints the code in an HTML representation.
- Parameters
listing –
Listing
object containing code to printsnippet – if True, prints out just the <div> containing the code. Otherwise, prints a full valid HTML file. Defaults to True.
- purdy.scribe.print_rtf(listing, background_colour=None)¶
Prints an RTF document containing the colourized code
- Parameters
listing –
Listing
object containing code to print
- purdy.scribe.print_tokens(listing, colour=True)¶
Prints each line in a
purdy.content.Code
object with a coloured background, then prints the parsed tokens inside that line- Parameters
listing –
purdy.content.Listing
object containing code to printcolour – set to True to print out using ANSI colour. Defaults to True
TUI Screen (purdy.tui.iscreen.py)¶
This module is an Urwid code viewer concrete implementation of a Screen. It is
constructed by purdy.ui.Screen
depending on its factory.
- class purdy.iscreen.tui.iscreen.BaseWindow(iscreen, *args, **kwargs)¶
- keypress(size, key)¶
Pass the keypress to the widget in focus. Unhandled ‘up’ and ‘down’ keys may cause a focus change.
- class purdy.iscreen.tui.iscreen.ConcreteCodeBox(proxy_code_box)¶
purdy.ui.CodeBox
represents a box of code in thepurdy.ui.Screen
. This is an Urwid implementation of it.- Parameters
proxy_code_box – the
purdy.ui.CodeBox
representing what is to be built.
- class purdy.iscreen.tui.iscreen.ConcreteTwinCodeBox(proxy)¶
purdy.ui.TwinCodeBox
represents two boxes of code in thepurdy.ui.Screen
, this is an Urwid implementation of it.- Parameters
proxy – the
purdy.ui.TwinCodeBox
representing what is to be built.
- class purdy.iscreen.tui.iscreen.HelpDialog(parent)¶
- keypress(size, key)¶
Pass the keypress to the widget in focus. Unhandled ‘up’ and ‘down’ keys may cause a focus change.
- class purdy.iscreen.tui.iscreen.TUIScreen(parent_screen)¶
Concrete, Urwid based implementation of a screen.
- Parameters
parent_screen –
purdy.ui.Screen
object that is creating this concrete implementation
- run()¶
Calls the main display event loop. Does not return until the UI exits.
Wigets (purdy.wigets.py)¶
Widgets for displaying. These are called and managed through the Screen
classes in purdy.ui
.
- class purdy.iscreen.tui.widgets.CodeWidget(screen, auto_scroll)¶
Urwid widget that displays the code. This implements the methods of
purdy.content.RenderHook
and is registered against apurdy.ui.CodeBox
andpurdy.content.Listing
. As changes are made to the listing they will be rendered this widget.The widget wraps an urwid ListBox, with each line in the box being a line of code. It also provides indiciators on the right side of the screen as to whether there is content above or below the current screen. If the parent
Screen
implementation has multiple instances of this class active, the scroll area will also indicate which code box is focused.The up and down arrows as well as the page-up and page-down buttons are supported. If there are multiple code widgets, tab key will change the focus.
- class purdy.iscreen.tui.widgets.DividingLine¶
- class purdy.iscreen.tui.widgets.ScrollingIndicator¶
- class purdy.iscreen.tui.widgets.ScrollingListBox(scroll_indicator, *args, **kwargs)¶
- keypress(size, key)¶
Move selection through the list elements scrolling when necessary. Keystrokes are first passed to widget in focus in case that widget can handle them.
- Keystrokes handled by this widget are:
‘up’ up one line (or widget) ‘down’ down one line (or widget) ‘page up’ move cursor up one listbox length (or widget) ‘page down’ move cursor down one listbox length (or widget)
- class purdy.iscreen.tui.widgets.TwinContainer(widget_list, dividechars=0, focus_column=None, min_width=1, box_columns=None)¶
Virtual Screen (purdy.virtual.iscreen.py)¶
This module mimics a code viewer, running through the requested actions and making the final result available.
- class purdy.iscreen.virtual.iscreen.VirtualScreen(parent_screen)¶
Concrete, Urwid based implementation of a screen.
- Parameters
parent_screen –
purdy.ui.Screen
object that is creating this concrete implementation
- run()¶
Runs the actions on the code listings.