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"
"github.com/bengarrett/bbs"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/transform"
)
//go:embed static/*
var 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.Print(err)
return
}
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.Print(err)
return
}
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.Print(err)
return
}
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 CelerityHTML(dst *bytes.Buffer, src []byte) error
- func IsCelerity(src []byte) bool
- func IsPCBoard(src []byte) bool
- func IsRenegade(src []byte) bool
- func IsTelegard(src []byte) bool
- func IsWWIVHash(src []byte) bool
- func IsWWIVHeart(src []byte) bool
- func IsWildcat(src []byte) bool
- func PCBoardHTML(dst *bytes.Buffer, src []byte) error
- func RenegadeHTML(dst *bytes.Buffer, src []byte) error
- func TelegardHTML(dst *bytes.Buffer, src []byte) error
- func TrimControls(src []byte) []byte
- func WWIVHashHTML(dst *bytes.Buffer, src []byte) error
- func WWIVHeartHTML(dst *bytes.Buffer, src []byte) error
- func WildcatHTML(dst *bytes.Buffer, src []byte) error
- type BBS
Examples ¶
Constants ¶
const ( // Clear is a PCBoard specific control to clear the screen that's occasionally found in ANSI text. Clear string = "@CLS@" // CelerityRe is a regular expression to match Celerity BBS color codes. CelerityRe 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. PCBoardRe string = "(?i)@X([0-9A-F][0-9A-F])" // RenegadeRe is a regular expression to match Renegade BBS color codes. RenegadeRe string = `\|(0[0-9]|1[1-9]|2[0-3])` // TelegardRe is a case-insensitive, regular expression to match Telegard BBS color codes. TelegardRe string = "(?i)`([0-9|A-F])([0-9|A-F])" // WildcatRe is a case-insensitive, regular expression to match Wildcat! BBS color codes. WildcatRe string = `(?i)@([0-9|A-F])([0-9|A-F])@` // WWIVHashRe is a regular expression to match WWIV BBS # color codes. WWIVHashRe string = `\|#(\d)` // WWIVHeartRe is a regular expression to match WWIV BBS ♥ color codes. WWIVHeartRe string = `\x03(\d)` )
Variables ¶
Functions ¶
func CelerityHTML ¶ added in v1.0.0
CelerityHTML 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 buf bytes.Buffer
src := []byte("|cHello |C|S|wworld")
if err := bbs.CelerityHTML(&buf, src); err != nil {
fmt.Print(err)
}
fmt.Print(buf.String())
}
Output: <i class="PBk PFc">Hello </i><i class="PBk PFC"></i><i class="PBw PFC">world</i>
func IsCelerity ¶ added in v1.0.0
IsCelerity 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("Is b Celerity BBS text? %v", bbs.IsCelerity(b))
}
Output: Is b Celerity BBS text? true
func IsPCBoard ¶ added in v1.0.0
IsPCBoard 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("Is b PCBoard BBS text? %v", bbs.IsPCBoard(b))
}
Output: Is b PCBoard BBS text? true
func IsRenegade ¶ added in v1.0.0
IsRenegade 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("Is b Renegade BBS text? %v", bbs.IsRenegade(b))
}
Output: Is b Renegade BBS text? true
func IsTelegard ¶ added in v1.0.0
IsTelegard 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("Is b Telegard BBS text? %v", bbs.IsTelegard(b))
}
Output: Is b Telegard BBS text? true
func IsWWIVHash ¶ added in v1.0.0
IsWWIVHash 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("Is b WVIV BBS # text? %v", bbs.IsWWIVHash(b))
}
Output: Is b WVIV BBS # text? true
func IsWWIVHeart ¶ added in v1.0.0
IsWWIVHeart 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("Is b WWIV BBS ♥ text? %v", bbs.IsWWIVHeart(b))
}
Output: Is b WWIV BBS ♥ text? true
func IsWildcat ¶ added in v1.0.0
IsWildcat 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("Is b Wildcat! BBS text? %v", bbs.IsWildcat(b))
}
Output: Is b Wildcat! BBS text? true
func PCBoardHTML ¶ added in v1.0.0
PCBoardHTML 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 buf bytes.Buffer
src := []byte("@X03Hello world")
if err := bbs.PCBoardHTML(&buf, src); err != nil {
log.Print(err)
}
fmt.Print(buf.String())
}
Output: <i class="PB0 PF3">Hello world</i>
func RenegadeHTML ¶ added in v1.0.0
RenegadeHTML 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 buf bytes.Buffer
src := []byte("|03Hello |07|19world")
if err := bbs.RenegadeHTML(&buf, src); err != nil {
log.Print(err)
}
fmt.Print(buf.String())
}
Output: <i class="P0 P3">Hello </i><i class="P0 P7"></i><i class="P19 P7">world</i>
func TelegardHTML ¶ added in v1.0.0
TelegardHTML writes to dst the HTML equivalent of Telegard BBS color codes with matching CSS color classes.
func TrimControls ¶
TrimControls removes common PCBoard BBS controls prefixes from the bytes. It trims the "@CLS@" prefix used to clear the screen and the "@PAUSE@" prefix used to pause the display render.
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
func WWIVHashHTML ¶ added in v1.0.0
WWIVHashHTML writes to dst the HTML equivalent of WWIV BBS # color codes with matching CSS color classes.
func WWIVHeartHTML ¶ added in v1.0.0
WWIVHeartHTML writes to dst the HTML equivalent of WWIV BBS ♥ color codes with matching CSS color classes.
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.ErrNone) {
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 buf bytes.Buffer
src := strings.NewReader("@X03Hello world")
if _, err := bbs.HTML(&buf, src); err != nil {
fmt.Print(err)
}
fmt.Print(buf.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"
"strings"
"github.com/bengarrett/bbs"
)
func main() {
var dst bytes.Buffer
if err := bbs.PCBoard.CSS(&dst); err != nil {
fmt.Print(err)
}
// print the first 8 lines
lines := strings.Split(dst.String(), "\n")
for i := 0; i < 8; i++ {
fmt.Println(lines[i])
}
}
Output: @import url("text_bbs.css"); @import url("text_blink.css"); /* PCBoard and WildCat! BBS colours */ i.PF0 { color: var(--black); }
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 buf bytes.Buffer
src := []byte("@X03Hello world")
if err := bbs.PCBoard.HTML(&buf, src); err != nil {
log.Print(err)
}
fmt.Print(buf.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 buf bytes.Buffer
src := []byte("@X03Hello @X07world")
if err := bbs.PCBoard.Remove(&buf, src); err != nil {
log.Print(err)
}
fmt.Printf("%q to %q", src, buf.String())
}
Output: "@X03Hello @X07world" to "Hello world"
Example (Find) ¶
package main
import (
"bytes"
"fmt"
"log"
"github.com/bengarrett/bbs"
)
func main() {
var buf bytes.Buffer
src := []byte("@X03Hello @X07world")
r := bytes.NewReader(src)
b := bbs.Find(r)
if err := b.Remove(&buf, src); err != nil {
log.Print(err)
}
fmt.Printf("%q to %q", src, buf.String())
}
Output: "@X03Hello @X07world" to "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