Encoding::Emacs

Auto-generated character encodings from Emacs MULE definitions - 80+ legacy encodings (ISO-8859, Windows CP, DOS CP, KOI8, EBCDIC, etc.)

Encoding::Emacs

Auto-generated character encodings from Emacs MULE definitions. Provides 80+ legacy character encodings for Raku, including ISO-8859, Windows codepages, DOS codepages, KOI8, EBCDIC, and more.

Installation

zef install Encoding::Emacs

Or from source:

git clone https://github.com/winfred-raj/encoding-emacs.git
cd encoding-emacs
zef install .

Quick Start

#!/usr/bin/env raku
use Encoding::Emacs::Full::Cp850;

# Decode CP850 bytes (DOS encoding with box-drawing chars)
my $bytes = Buf.new(0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x9D);  # "Hello Ø"
my $decoder = Encoding::Emacs::Full::Cp850.decoder;
my $text = $decoder.consume($bytes);
say $text;  # Output: Hello Ø

# Encode Unicode string to CP850
my $encoder = Encoding::Emacs::Full::Cp850.encoder;
my $encoded = $encoder.encode-chars("Grüß Gott");
say $encoded;  # Output: Buf:0x<47 72 81 E1 20 47 6F 74 74>

Supported Encodings

ISO-8859 Series (Latin)

  • ISO-8859-2 (Central European)

  • ISO-8859-3 (South European)

  • ISO-8859-4 (North European)

  • ISO-8859-5 (Cyrillic)

  • ISO-8859-6 (Arabic)

  • ISO-8859-7 (Greek)

  • ISO-8859-8 (Hebrew)

  • ISO-8859-9 (Turkish)

  • ISO-8859-14 (Celtic)

  • ISO-8859-15 (Latin-9 with Euro sign)

Windows Codepages

  • CP1250 (Central European)

  • CP1251 (Cyrillic)

  • CP1252 (Western European)

  • CP1253 (Greek)

  • CP1254 (Turkish)

  • CP1255 (Hebrew)

  • CP1256 (Arabic)

  • CP1257 (Baltic)

  • CP1258 (Vietnamese)

DOS Codepages

  • CP437 (Original IBM PC)

  • CP850 (Western European)

  • CP852 (Central European)

  • CP855, CP857, CP860-865 (Various regions)

  • CP866 (Russian)

KOI8 Variants

  • KOI8-R (Russian)

  • KOI8-U (Ukrainian)

  • KOI8-T (Tajik)

Other Legacy Encodings

  • Mac Roman

  • HP Roman8

  • VISCII (Vietnamese)

  • IBM EBCDIC variants

  • And 50+ more!

Usage Examples

Decode Legacy Files

use Encoding::Emacs::Full::Iso_8859_5;  # Cyrillic

my $bytes = slurp("old-file.txt", :bin);
my $decoder = Encoding::Emacs::Full::Iso_8859_5.decoder;
my $text = $decoder.consume($bytes);
say $text;  # Readable Russian text

Encode for Legacy Systems

use Encoding::Emacs::Full::Windows_1252;

my $unicode-text = "CafΓ© rΓ©sumΓ©";
my $encoder = Encoding::Emacs::Full::Windows_1252.encoder;
my $bytes = $encoder.encode-chars($unicode-text);
spurt("output.txt", $bytes);

Round-Trip Conversion

use Encoding::Emacs::Full::Cp866;  # Russian DOS

my $original = "ΠŸΡ€ΠΈΠ²Π΅Ρ‚ ΠΌΠΈΡ€!";
my $encoder = Encoding::Emacs::Full::Cp866.encoder;
my $decoder = Encoding::Emacs::Full::Cp866.decoder;

my $encoded = $encoder.encode-chars($original);
my $decoded = $decoder.consume($encoded);

say $decoded eq $original;  # True

Encoding::Registry Integration

Encoding::Emacs::Registry bridges these encodings into Raku's built-in Encoding::Registry. Just use it once and all supported single-byte encodings are registered by name (and alias):

use Encoding::Emacs::Registry;

# Look encodings up by name through the standard registry
my $bytes = Buf.new(0x41, 0xB5);
say emacs-decode($bytes, "cp850");        # AÁ
say emacs-encode("AÁ", "cp850");          # Buf:0x<41 B5>

# Or go through Encoding::Registry directly
my $dec = Encoding::Registry.find("cp850").decoder;
$dec.add-bytes($bytes);
say $dec.consume-all-chars;               # AÁ

emacs-decode / emacs-encode are convenience wrappers because Raku's Buf.decode does not route through Encoding::Registry; use them when you want a one-call decode/encode by encoding name.

How It Works

This module parses Emacs' MULE (Multilingual Environment) charset definitions and mapping tables to automatically generate Raku encoding classes. Each encoding:

  1. Lazy loads mapping tables on first use

  2. Caches mappings for performance

  3. Uses hash-based O(1) lookups for encode/decode

  4. Implements Raku's Encoding::Encoder and Encoding::Decoder roles

Performance

  • Mapping load: O(n) - done once per encoding, then cached

  • Decode: O(m) - where m = bytes in input

  • Encode: O(k) - where k = characters in input

  • Memory: ~1-2 KB per loaded encoding

Architecture

Encoding::Emacs/
β”œβ”€β”€ Parser.rakumod          # Parses Emacs Lisp charset definitions
β”œβ”€β”€ Generator.rakumod       # Generates Raku encoding classes
β”œβ”€β”€ MappingTable.rakumod    # Runtime mapping table loader
└── Full/                   # 81 generated encoding classes
    β”œβ”€β”€ Iso_8859_5.rakumod
    β”œβ”€β”€ Cp850.rakumod
    β”œβ”€β”€ Windows_1252.rakumod
    └── ...

Development

Generate Encodings

raku bin/generate-encodings.raku emacs-src/mule-conf.el lib/Encoding/Emacs/Full

Run Tests

raku -I lib t/01-parser.rakutest          # Parser tests
raku -I lib t/02-generator.rakutest       # Generator tests
raku -I lib t/03-mapping-table.rakutest   # Mapping loader tests
raku -I lib t/04-encoding-decoding.rakutest  # Encode/decode tests
raku -I lib t/05-phase3-encode-decode.rakutest  # Round-trip tests
raku -I lib t/06-cp850-encoding.rakutest  # CP850 specific tests

All 52 tests should pass.

Status

  • βœ… Phase 1: Parser - Complete

  • βœ… Phase 2: Code Generator - Complete

  • βœ… Phase 3: Mapping Tables - Complete

  • βœ… Phase 4: Encoding::Registry integration - Complete

Limitations

  • Currently supports single-byte encodings only

  • Multi-byte encodings (UTF-16, Shift-JIS, EUC, Big5, etc.) are in the mapping files but require additional implementation

Contributing

Contributions welcome! Please:

  1. Fork the repository

  2. Create a feature branch

  3. Add tests for new functionality

  4. Ensure all tests pass

  5. Submit a pull request

License

Artistic License 2.0 (same as Raku)

Author

Winfred Raj

See Also

Acknowledgments

Built using Emacs' comprehensive MULE (Multilingual Environment) charset definitions and mapping tables, originally created by the GNU Emacs team.

Encoding::Emacs v0.1.5.1

Auto-generated character encodings from Emacs MULE definitions - 80+ legacy encodings (ISO-8859, Windows CP, DOS CP, KOI8, EBCDIC, etc.)

Authors

  • Winfred Raj

License

Artistic-2.0

Dependencies

Test Dependencies

Provides

  • Encoding::Emacs::Full::Alternativnyj
  • Encoding::Emacs::Full::Control_1
  • Encoding::Emacs::Full::Cp00858
  • Encoding::Emacs::Full::Cp1125
  • Encoding::Emacs::Full::Cp1250
  • Encoding::Emacs::Full::Cp1251
  • Encoding::Emacs::Full::Cp1252
  • Encoding::Emacs::Full::Cp1253
  • Encoding::Emacs::Full::Cp1254
  • Encoding::Emacs::Full::Cp1255
  • Encoding::Emacs::Full::Cp1256
  • Encoding::Emacs::Full::Cp1257
  • Encoding::Emacs::Full::Cp1258
  • Encoding::Emacs::Full::Cp437
  • Encoding::Emacs::Full::Cp720
  • Encoding::Emacs::Full::Cp737
  • Encoding::Emacs::Full::Cp775
  • Encoding::Emacs::Full::Cp850
  • Encoding::Emacs::Full::Cp851
  • Encoding::Emacs::Full::Cp852
  • Encoding::Emacs::Full::Cp855
  • Encoding::Emacs::Full::Cp857
  • Encoding::Emacs::Full::Cp858
  • Encoding::Emacs::Full::Cp860
  • Encoding::Emacs::Full::Cp861
  • Encoding::Emacs::Full::Cp862
  • Encoding::Emacs::Full::Cp863
  • Encoding::Emacs::Full::Cp864
  • Encoding::Emacs::Full::Cp865
  • Encoding::Emacs::Full::Cp866
  • Encoding::Emacs::Full::Cp866u
  • Encoding::Emacs::Full::Cp869
  • Encoding::Emacs::Full::Cp874
  • Encoding::Emacs::Full::Georgian_Academy
  • Encoding::Emacs::Full::Georgian_Ps
  • Encoding::Emacs::Full::Hp_Roman8
  • Encoding::Emacs::Full::Ibm850
  • Encoding::Emacs::Full::Ibm866
  • Encoding::Emacs::Full::Iso_8859_14
  • Encoding::Emacs::Full::Iso_8859_15
  • Encoding::Emacs::Full::Iso_8859_2
  • Encoding::Emacs::Full::Iso_8859_3
  • Encoding::Emacs::Full::Iso_8859_4
  • Encoding::Emacs::Full::Iso_8859_5
  • Encoding::Emacs::Full::Iso_8859_6
  • Encoding::Emacs::Full::Iso_8859_7
  • Encoding::Emacs::Full::Iso_8859_8
  • Encoding::Emacs::Full::Iso_8859_9
  • Encoding::Emacs::Full::Japanese_Jisx0213_A
  • Encoding::Emacs::Full::Koi8
  • Encoding::Emacs::Full::Koi8_R
  • Encoding::Emacs::Full::Koi8_T
  • Encoding::Emacs::Full::Koi8_U
  • Encoding::Emacs::Full::Latin_Iso8859_1
  • Encoding::Emacs::Full::Mac_Roman
  • Encoding::Emacs::Full::Mik
  • Encoding::Emacs::Full::Next
  • Encoding::Emacs::Full::Ruscii
  • Encoding::Emacs::Full::Tcvn_5712
  • Encoding::Emacs::Full::Unicode_Bmp
  • Encoding::Emacs::Full::Viscii
  • Encoding::Emacs::Full::Vscii
  • Encoding::Emacs::Full::Vscii_2
  • Encoding::Emacs::Full::Windows_1250
  • Encoding::Emacs::Full::Windows_1251
  • Encoding::Emacs::Full::Windows_1252
  • Encoding::Emacs::Full::Windows_1253
  • Encoding::Emacs::Full::Windows_1254
  • Encoding::Emacs::Full::Windows_1255
  • Encoding::Emacs::Full::Windows_1256
  • Encoding::Emacs::Full::Windows_1257
  • Encoding::Emacs::Full::Windows_1258
  • Encoding::Emacs::Generator
  • Encoding::Emacs::MappingTable
  • Encoding::Emacs::Parser
  • Encoding::Emacs::Registry

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.