Pb

pb is an esoteric programming language created by User:undergroundmonorail in 2015. It is a 2D language, but not in the sense of Befunge or ><>. Instead, the terminal is thought of as a 2D "canvas". The programmer moves their "paintbrush" to whatever location they wish to output to, and do so. This makes pb difficult to use for most purposes, as a string must be printed character by character, with the brush being moved between each one. However, it does allow for easier text placement, without having to fool around with newlines and spaces to adjust a character's position. pb's interpreter, pbi, can be found in the github repo for the language.

By convention, pb programs use the file type. But don't let me tell you what to do. The interpreter accepts anything; go nuts.

Palette
A painter is nothing without their palette. In pb, the palette is a set of predefined variables. No additional variables may be defined.

Anywhere that a colour is referred to, they are represented by these numbers:

Commands
pb understands the following commands:

while
The only conditional branch/loop structure possible in pb is the while loop. A while loop is created with the  command and is followed by a pair of square brackets and a pair of curly braces, like so:. The square brackets contain the condition for the while loop, and the curly braces contain pb code to be executed until the condition is no longer true. The condition is made up of three parts: Two numbers and/or expressions, separated by the character  or. If the character in the middle is, the code will be run until both sides evaluate to different things. If it's, the code will be run until they evaluate to the same thing.

Canvas
The canvas is an infinite 2D plane represented by the terminal, starting in the upper left corner at (0, 0). The canvas spreads in all four directions. If the  command is used while the brush is at a negative X coordinate, a negative Y coordinate, or both, the resulting character will not be printed to the screen. However, it will be saved in the program's memory. Going back to that same coordinate later will set the  variable to whatever you printed.

Input
Assume the user enters a string of input that is n characters long. Input is kept at (0, -1), (1, -1)... (n, -1). All input is white.

Input is collected all at once at pbi's initialization, whether it's required by the program or not. When I stop being so lazy I'll update pbi to assume no input at first, then ask for it if the program tries to read a character at Y=-1. It will still all be collected at once.

cat.pb
^w[B!0]{t[B]vb[T]^>}

^       # Go to the first byte of input w[B!0]{ # While B != 0 t[B]  # Store B in the variable T   vb[T]  # Go down to Y=0 and write the contents of T   ^>     # Go to the next byte of input. }       # Repeat if B != 0

reverse.pb
^w[B!0]{w[B!0]{>}}b[T]<[X]^}

^          # Go to the first byte of input w[B!0]{    # While B != 0 w[B!0]{>} # Go right until B = 0 <        # Go left to find the last place where B is not 0 t[B]b[0] # Store B in T, then write 0 <[X]v    # Go to to (0, 0) w[B!0]{>} # Go right until B = 0 b[T]     # Write the contents of B   <[X]^     # Go to (0, -1) }          # Repeat if B != 0

rainbow.pb
This program takes the first byte of input and prints it in every colour in the language, including black (invisible, but it's there I promise). Here's an example:



^t[B]vb[T]cw[P!0]{>b[T]c}

^t[B]v # Set T to the first byte of input b[T]   # Write T at (0, 0) c      # Cycle the output colour w[P!0]{ # While the output colour != 0 (white) >b[T] # Move right and write T again c    # Cycle the output colour }      # Repeat if the output colour != 0 (white)