Documentation
¶
Overview ¶
Package bbs interacts with legacy textfiles encoded with Bulletin Board Systems (BBS) color codes to reconstruct them into HTML documents.
BBSes were popular in the 1980s and 1990s, and allowed computer users to chat, message, and share files over the landline telephone network. The commercialization and ease of access to the Internet eventually replaced BBSes, as did the world-wide-web.
These centralized systems, termed boards, used a text-based interface, and their owners often applied colorization, text themes, and art to differentiate themselves.
While in the 1990s, ANSI control codes were in everyday use on the PC/MS-DOS, the standard comes from mainframe equipment. Home microcomputers often had difficulty interpreting it. So BBS developers created their own, more straightforward methods to colorize and theme the text output to solve this.
*Please note, while many PC/MS-DOS boards used ANSI control codes for colorizations, this library does not support the standard.
PCBoard ¶
One of the most well-known applications for hosting a PC/MS-DOS BBS, PCBoard pioneered the file_id.diz file descriptor, as well as being endlessly expandable through software plugins known as PPEs. It developed the popular @X color code and @ control syntax.
Celerity ¶
Another PC/MS-DOS application that was very popular with the hacking, phreaking, and pirate communities in the early 1990s. It introduced a unique | pipe code syntax in late 1991 that revised the code syntax in version 2 of the software.
Renegade ¶
A PC/MS-DOS application that was a derivative of the source code of Telegard BBS. Surprisingly there was a new release of this software in 2021. Renegade had two methods to implement color, and this library uses the Pipe Bar Color Codes.
Telegard ¶
A PC/MS-DOS application became famous due to a source code leak or release by one of its authors back in an era when most developers were still highly secretive with their code. The source is incorporated into several other projects.
WVIV ¶
A mainstay in the PC/MS-DOS BBS scene of the 1980s and early 1990s, it became well known for releasing its source code to registered users. It allowed them to expand the code to incorporate additional software such as games or utilities and port it to other platforms. The source is now Open Source and is still updated. Confusingly WWIV has three methods of colorizing text, 10 Pipe colors, two-digit pipe colors, and its original Heart Codes.
Wildcat ¶
WILDCAT! was a popular, propriety PC/MS-DOS application from the late 1980s that later migrated to Windows. It was one of the few BBS applications that sold at retail in a physical box. It extensively used @ color codes throughout later revisions of its software.
Example ¶
package main
import (
"bytes"
"embed"
"fmt"
"log"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/transform"
"github.com/bengarrett/bbs"
)
var (
//go:embed static/*
static embed.FS
)
func main() {
// print about the file
file, err := static.Open("static/examples/hello.pcb")
if err != nil {
log.Fatal(err)
}
defer file.Close()
s, b, err := bbs.Fields(file)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d %s color controls.\n\n", len(s), b)
// reopen the file
file, err = static.Open("static/examples/hello.pcb")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// transform the MS-DOS legacy text to Unicode
decoder := charmap.CodePage437.NewDecoder()
reader := transform.NewReader(file, decoder)
// create the HTML equivalent of BBS color codes
var buf bytes.Buffer
if _, err := bbs.HTML(&buf, reader); err != nil {
log.Fatal(err)
}
fmt.Print(buf.String())
}
Output: Found 11 PCBoard @X color controls. <i class="PB0 PFF"> </i><i class="PB7 PF0"> ┌─────────────┐ </i><i class="PB0 PF7"> </i><i class="PB0 PFF"> </i><i class="PB7 PF0"> │ Hello </i><i class="PBF PF0">world </i><i class="PB7 PF0">│ </i><i class="PB0 PF7"> </i><i class="PB0 PFF"> </i><i class="PB7 PF0"> └─────────────┘ </i><i class="PB0 PF7"></i>
Index ¶
- Constants
- Variables
- func HTMLCelerity(dst *bytes.Buffer, src []byte) error
- func HTMLPCBoard(dst *bytes.Buffer, src []byte) error
- func HTMLRenegade(dst *bytes.Buffer, src []byte) error
- func HTMLTelegard(dst *bytes.Buffer, src []byte) error
- func HTMLWHash(dst *bytes.Buffer, src []byte) error
- func HTMLWHeart(dst *bytes.Buffer, src []byte) error
- func HTMLWildcat(dst *bytes.Buffer, src []byte) error
- func HasCelerity(src []byte) bool
- func HasPCBoard(src []byte) bool
- func HasRenegade(src []byte) bool
- func HasTelegard(src []byte) bool
- func HasWHash(src []byte) bool
- func HasWHeart(src []byte) bool
- func HasWildcat(src []byte) bool
- func TrimControls(src []byte) []byte
- type BBS
Examples ¶
Constants ¶
const ( // ClearCmd is a PCBoard specific control to clear the screen that's occasionally found in ANSI text. ClearCmd string = "@CLS@" // CelerityMatch is a regular expression to match Celerity BBS color codes. CelerityMatch string = `\|(k|b|g|c|r|m|y|w|d|B|G|C|R|M|Y|W|S)` // PCBoardMatch is a case-insensitive, regular expression to match PCBoard BBS color codes. PCBoardMatch string = "(?i)@X([0-9A-F][0-9A-F])" // RenegadeMatch is a regular expression to match Renegade BBS color codes. RenegadeMatch string = `\|(0[0-9]|1[1-9]|2[0-3])` // TelegardMatch is a case-insensitive, regular expression to match Telegard BBS color codes. TelegardMatch string = "(?i)`([0-9|A-F])([0-9|A-F])" // WildcatMatch is a case-insensitive, regular expression to match Wildcat! BBS color codes. WildcatMatch string = `(?i)@([0-9|A-F])([0-9|A-F])@` // WWIVHashMatch is a regular expression to match WWIV BBS # color codes. WWIVHashMatch string = `\|#(\d)` // WWIVHeartMatch is a regular expression to match WWIV BBS ♥ color codes. WWIVHeartMatch string = `\x03(\d)` )
Variables ¶
var ( ErrColorCodes = errors.New("no bbs color codes found") ErrANSI = errors.New("ansi escape code found") )
Functions ¶
func HTMLCelerity ¶
HTMLCelerity writes to dst the HTML equivalent of Celerity BBS color codes with matching CSS color classes.
Example ¶
package main
import (
"bytes"
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
var out bytes.Buffer
src := []byte("|cHello |C|S|wworld")
if err := bbs.HTMLCelerity(&out, src); err != nil {
fmt.Print(err)
}
fmt.Print(out.String())
}
Output: <i class="PBk PFc">Hello </i><i class="PBk PFC"></i><i class="PBw PFC">world</i>
func HTMLPCBoard ¶
HTMLPCBoard writes to dst the HTML equivalent of PCBoard BBS color codes with matching CSS color classes.
Example ¶
package main
import (
"bytes"
"fmt"
"log"
"github.com/bengarrett/bbs"
)
func main() {
var out bytes.Buffer
src := []byte("@X03Hello world")
if err := bbs.HTMLPCBoard(&out, src); err != nil {
log.Print(err)
}
fmt.Print(out.String())
}
Output: <i class="PB0 PF3">Hello world</i>
func HTMLRenegade ¶
HTMLRenegade writes to dst the HTML equivalent of Renegade BBS color codes with matching CSS color classes.
Example ¶
package main
import (
"bytes"
"fmt"
"log"
"github.com/bengarrett/bbs"
)
func main() {
var out bytes.Buffer
src := []byte("|03Hello |07|19world")
if err := bbs.HTMLRenegade(&out, src); err != nil {
log.Print(err)
}
fmt.Print(out.String())
}
Output: <i class="P0 P3">Hello </i><i class="P0 P7"></i><i class="P19 P7">world</i>
func HTMLTelegard ¶
HTMLTelegard writes to dst the HTML equivalent of Telegard BBS color codes with matching CSS color classes.
func HTMLWHash ¶
HTMLWildcat writes to dst the HTML equivalent of WWIV BBS # color codes with matching CSS color classes.
func HTMLWHeart ¶
HTMLWildcat writes to dst the HTML equivalent of WWIV BBS ♥ color codes with matching CSS color classes.
func HTMLWildcat ¶
HTMLWildcat writes to dst the HTML equivalent of Wildcat! BBS color codes with matching CSS color classes.
func HasCelerity ¶
HasCelerity reports if the bytes contains Celerity BBS color codes. The format uses the vertical bar "|" followed by a case sensitive single alphabetic character.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := []byte("|cHello |C|S|wworld")
fmt.Printf("Has b Celerity BBS text? %v", bbs.HasCelerity(b))
}
Output: Has b Celerity BBS text? true
func HasPCBoard ¶
HasPCBoard reports if the bytes contains PCBoard BBS color codes. The format uses an "@X" prefix with a background and foreground, 4-bit hexadecimal color value.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := []byte("@X03Hello world")
fmt.Printf("Has b PCBoard BBS text? %v", bbs.HasPCBoard(b))
}
Output: Has b PCBoard BBS text? true
func HasRenegade ¶
HasRenegade reports if the bytes contains Renegade BBS color codes. The format uses the vertical bar "|" followed by a padded, numeric value between 00 and 23.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := []byte("|03Hello |07|19world")
fmt.Printf("Has b Renegade BBS text? %v", bbs.HasRenegade(b))
}
Output: Has b Renegade BBS text? true
func HasTelegard ¶
HasTelegard reports if the bytes contains Telegard BBS color codes. The format uses the grave accent followed by a padded, numeric value between 00 and 23.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
const grave = "\u0060" // godoc treats a grave character as a special control
b := []byte(grave + "7Hello world")
fmt.Printf("Has b Telegard BBS text? %v", bbs.HasTelegard(b))
}
Output: Has b Telegard BBS text? true
func HasWHash ¶
HasWHash reports if the bytes contains WWIV BBS # (hash or pound) color codes. The format uses a vertical bar "|" with the hash "#" characters as a prefix with a numeric value between 0 and 9.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := []byte("|#7Hello world")
fmt.Printf("Has b WVIV BBS # text? %v", bbs.HasWHash(b))
}
Output: Has b WVIV BBS # text? true
func HasWHeart ¶
HasWHeart reports if the bytes contains WWIV BBS ♥ (heart) color codes. The format uses the ETX character as a prefix with a numeric value between 0 and 9. In the standard MS-DOS, USA codepage (CP-437), the ETX (end-of-text) character is substituted with a heart character.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := []byte("\x037Hello world")
fmt.Printf("Has b WWIV BBS ♥ text? %v", bbs.HasWHeart(b))
}
Output: Has b WWIV BBS ♥ text? true
func HasWildcat ¶
HasWildcat reports if the bytes contains Wildcat! BBS color codes. The format uses an a background and foreground, 4-bit hexadecimal color value enclosed by two at "@" characters.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := []byte("@0F@Hello world")
fmt.Printf("Has b Wildcat! BBS text? %v", bbs.HasWildcat(b))
}
Output: Has b Wildcat! BBS text? true
func TrimControls ¶
TrimControls removes common PCBoard BBS controls prefixes from the bytes.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := []byte("@CLS@@PAUSE@Hello world")
r := bbs.TrimControls(b)
fmt.Print(string(r))
}
Output: Hello world
Types ¶
type BBS ¶
type BBS int
Bulletin Board System color code format. Other than for Find, the ANSI type is not supported by this library.
func Fields ¶
Fields splits the io.Reader around the first instance of one or more consecutive BBS color codes. An error is returned if no color codes are found or if ANSI control sequences are first found.
Example ¶
package main
import (
"fmt"
"log"
"strings"
"github.com/bengarrett/bbs"
)
func main() {
r := strings.NewReader("@X03Hello @XF0world")
s, b, err := bbs.Fields(r)
if err != nil {
log.Print(err)
}
fmt.Printf("Found %d %s sequences.", len(s), b)
}
Output: Found 2 PCBoard @X sequences.
Example (None) ¶
package main
import (
"errors"
"fmt"
"strings"
"github.com/bengarrett/bbs"
)
func main() {
r := strings.NewReader("Hello world.")
_, _, err := bbs.Fields(r)
if errors.Is(err, bbs.ErrColorCodes) {
fmt.Print(err)
}
}
Output: no bbs color codes found
func Find ¶
Find the format of any known BBS color code sequence within the reader. If no sequences are found -1 is returned.
Example ¶
package main
import (
"fmt"
"strings"
"github.com/bengarrett/bbs"
)
func main() {
r := strings.NewReader("@X03Hello world")
f := bbs.Find(r)
fmt.Printf("Reader is in a %s BBS format", f.Name())
}
Output: Reader is in a PCBoard BBS format
Example (None) ¶
package main
import (
"fmt"
"strings"
"github.com/bengarrett/bbs"
)
func main() {
r := strings.NewReader("Hello world")
f := bbs.Find(r)
if !f.Valid() {
fmt.Print("reader is plain text")
}
}
Output: reader is plain text
func HTML ¶
HTML writes to dst the HTML equivalent of BBS color codes with matching CSS color classes. The first found color code format is used for the remainder of the Reader.
Example ¶
package main
import (
"bytes"
"fmt"
"strings"
"github.com/bengarrett/bbs"
)
func main() {
var out bytes.Buffer
src := strings.NewReader("@X03Hello world")
if _, err := bbs.HTML(&out, src); err != nil {
fmt.Print(err)
}
fmt.Print(out.String())
}
Output: <i class="PB0 PF3">Hello world</i>
func (BBS) Bytes ¶
Bytes returns the BBS color toggle sequence as bytes.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
b := bbs.PCBoard.Bytes()
fmt.Printf("%s %v", b, b)
}
Output: @X [64 88]
func (BBS) CSS ¶
CSS writes to dst the Cascading Style Sheets classes needed by the HTML. The CSS relies on cascading variables. See https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties for details.
Example ¶
package main
import (
"bytes"
"fmt"
"log"
"os"
"github.com/bengarrett/bbs"
)
func main() {
var buf bytes.Buffer
if err := bbs.PCBoard.CSS(&buf); err != nil {
fmt.Print(err)
}
f, err := os.OpenFile("pcboard.css", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer os.Remove(f.Name()) // clean up
if _, err := buf.WriteTo(f); err != nil {
log.Fatal(err)
}
}
Output:
func (BBS) HTML ¶
HTML writes to dst the HTML equivalent of BBS color codes with matching CSS color classes.
Example ¶
package main
import (
"bytes"
"fmt"
"log"
"github.com/bengarrett/bbs"
)
func main() {
var out bytes.Buffer
src := []byte("@X03Hello world")
if err := bbs.PCBoard.HTML(&out, src); err != nil {
log.Print(err)
}
fmt.Print(out.String())
}
Output: <i class="PB0 PF3">Hello world</i>
func (BBS) Name ¶
Name returns the name of the BBS color format.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
fmt.Print(bbs.PCBoard.Name())
}
Output: PCBoard
func (BBS) Remove ¶
Remove the BBS color codes from src and write it to dst.
Example ¶
package main
import (
"bytes"
"fmt"
"log"
"github.com/bengarrett/bbs"
)
func main() {
var out bytes.Buffer
src := []byte("@X03Hello @X07world")
if err := bbs.PCBoard.Remove(&out, src); err != nil {
log.Print(err)
}
fmt.Print(out.String())
}
Output: Hello world
Example (Find) ¶
package main
import (
"bytes"
"fmt"
"log"
"github.com/bengarrett/bbs"
)
func main() {
var out bytes.Buffer
src := []byte("@X03Hello @X07world")
r := bytes.NewReader(src)
b := bbs.Find(r)
if err := b.Remove(&out, src); err != nil {
log.Print(err)
}
fmt.Print(out.String())
}
Output: Hello world
func (BBS) String ¶
String returns the BBS color format name and toggle sequence.
Example ¶
package main
import (
"fmt"
"github.com/bengarrett/bbs"
)
func main() {
fmt.Print(bbs.PCBoard)
}
Output: PCBoard @X